Module 3: Analysing results produce from Modules 1 and 2

library(png)

Consolidate available files into a single table

## First consolidate the available files into a single table
    
      path <- "~/Box Sync/Four model compare/Module 2"
           
     
           setwd(path)
    myfiles_full <- list.dirs()
    analyze_this_many <- length(myfiles_full)
    
    available_files <- matrix(NA, 1, 1)
    
        
    for(i in 1: analyze_this_many){
    available_files <- rbind(available_files , as.matrix(list.files(myfiles_full[i], full.names = TRUE)))
    }
    dim(available_files)
    
    split.file.name <- strsplit(available_files[10], split = "_") 
    
    
    
 
available <- list.files()
files <- matrix(rep(NA, 62), length(available), 62)
dim(files)
i <- 10


for(i in 1:length(available)){
load(available[i])
name <- unlist(strsplit(available[i], split="_"))
files[i,] <- c(as.vector(matrix(name, 1,35)),matrix(Sim_statistics[[1]], 1, 27))

}


colnames(files) <-  c(

    NA,
    "background_takeover_type" ,
    NA,
    "replicate",
    NA,
    "Model_type",
    rep(NA,2),
    "speciation_of_Env_NonD",
    "speciation_of_Env_D",
    "speciation_of_For",
    "speciation_of_Dom",
    NA,
    "extinction_of_Env_NonD",
    "extinction_of_Env_D",
    "extinction_of_For",
    "extinction_of_Dom",
    NA,
    "P.diffusion_Target_forager",
    "P.diffusion_Target_domesticator",
    "P.diffusion_Source_forager",
    "P.diffusion_Source_domesticator",
    NA,
    "P.takeover_Target_forager",
    "P.takeover_Target_domesticator",
    "P.takeover_Source_forager",
    "P.takeover_Source_domesticator",
    NA,
    "arisal_of_Env_NonD",
    "arisal_of_Env_D",
    "arisal_of_For",
    "arisal_of_Dom",
    
    NA, 
    "timesteps", 
    NA,
        
    "number_of_branches",
    "Pylo_diversity_is_sum_of_BL",
    "average_phylogenetic_diversity_is_mean_of_BL",
    "variance_Pylo_diversity_is_variance_of_BL",

    "F_quadratic_entropy_is_sum_of_PD",
    "Mean_pairwise_distance",
    "variance_pairwise_distance",

    "Evolutionary_distinctiveness_sum",
    "mean_Phylogenetic_isolation",
    "variance_Phylogenetic_isolation",

    "gamma",
    "gamma_p_value",
    "speciation_rate",
    "extinction_rate",
    "extinction_per_speciation",
    "speciation_minus_extinction",
    "trait_1_speciation",
    "trait_2_speciation" ,
    "trait_1_extinction" ,
    "trait_2_extinction" ,
    "transition_from_trait_1_to_2" ,
    "transition_from_trait_2_to_1" ,
    "transition_rate_ratio_1to2_over_2to1" ,
    "Phylogenetic_signal",
    "spatial.tests.fora",
    "spatial.tests.dom",
    "prevalence"
    
    
  )

results_table <- as.data.frame(files)
head(results_table)
dim(results_table)
Concatenated_data <- results_table
save(Concatenated_data, file="~/Desktop/Four_model_compare_results.Rdata")

one <- subset(results_table, Model_type=="01" )
two <- subset(results_table, Model_type=="02" )
three <- subset(results_table, Model_type=="03" )
four <- subset(results_table, Model_type=="04" )
crop <- min(length(one[,1]),
length(two[,1]),
length(three[,1]),
length(four[,1]))
one <- one[1:crop,]
two <- two[1:crop,]
three <- three[1:crop,]
four <- four[1:crop,]

Concatenated_data <- rbind(one, two, three, four)
dim(Concatenated_data)





save(Concatenated_data, file=paste0("~/Box Sync/colliding ranges/Simulations_humans/Results/available daily summaries/Four_model_compare_results", format(Sys.time(), format="%d_%b_%Y"),"_crop_to_", crop,".Rdata"))
crop
## First consolidate the available files into a single table
    
      path <- "~/Box Sync/Four model compare/Module 2 extinct"
           
     
           setwd(path)
    myfiles_full <- list.dirs()
    analyze_this_many <- length(myfiles_full)
    
    available_files <- matrix(NA, 1, 1)
    
        
    for(i in 1: analyze_this_many){
    available_files <- rbind(available_files , as.matrix(list.files(myfiles_full[i], full.names = TRUE)))
    }
    dim(available_files)
    
    split.file.name <- strsplit(available_files[10], split = "_") 
    
    
    
 
available <- list.files()
files <- matrix(rep(NA, 62), length(available), 62)
dim(files)
i <- 10


for(i in 1:length(available)){
load(available[i])
name <- unlist(strsplit(available[i], split="_"))
files[i,] <- c(as.vector(matrix(name, 1,35)),matrix(Sim_statistics[[1]], 1, 27))

}


colnames(files) <-  c(

    NA,
    "background_takeover_type" ,
    NA,
    "replicate",
    NA,
    "Model_type",
    rep(NA,2),
    "speciation_of_Env_NonD",
    "speciation_of_Env_D",
    "speciation_of_For",
    "speciation_of_Dom",
    NA,
    "extinction_of_Env_NonD",
    "extinction_of_Env_D",
    "extinction_of_For",
    "extinction_of_Dom",
    NA,
    "P.diffusion_Target_forager",
    "P.diffusion_Target_domesticator",
    "P.diffusion_Source_forager",
    "P.diffusion_Source_domesticator",
    NA,
    "P.takeover_Target_forager",
    "P.takeover_Target_domesticator",
    "P.takeover_Source_forager",
    "P.takeover_Source_domesticator",
    NA,
    "arisal_of_Env_NonD",
    "arisal_of_Env_D",
    "arisal_of_For",
    "arisal_of_Dom",
    
    NA, 
    "timesteps", 
    NA,
        
    "number_of_branches",
    "Pylo_diversity_is_sum_of_BL",
    "average_phylogenetic_diversity_is_mean_of_BL",
    "variance_Pylo_diversity_is_variance_of_BL",

    "F_quadratic_entropy_is_sum_of_PD",
    "Mean_pairwise_distance",
    "variance_pairwise_distance",

    "Evolutionary_distinctiveness_sum",
    "mean_Phylogenetic_isolation",
    "variance_Phylogenetic_isolation",

    "gamma",
    "gamma_p_value",
    "speciation_rate",
    "extinction_rate",
    "extinction_per_speciation",
    "speciation_minus_extinction",
    "trait_1_speciation",
    "trait_2_speciation" ,
    "trait_1_extinction" ,
    "trait_2_extinction" ,
    "transition_from_trait_1_to_2" ,
    "transition_from_trait_2_to_1" ,
    "transition_rate_ratio_1to2_over_2to1" ,
    "Phylogenetic_signal",
    "spatial.tests.fora",
    "spatial.tests.dom",
    "prevalence"
    
    
  )

Concatenated_data <- as.data.frame(files)
head(Concatenated_data)
dim(Concatenated_data)

save(Concatenated_data, file=paste0("~/Box Sync/colliding ranges/Simulations_humans/Results/available daily summaries/Four_model_compare_results_extinct_", format(Sys.time(), format="%d_%b_%Y"),"_crop_to_", crop,".Rdata"))

Summarize overall extinction rates

load('~/Box Sync/colliding ranges/Simulations_humans/Results/available daily summaries/Four_model_compare_results_02_Mar_2017_crop_to_3481.Rdata')
extant <- Concatenated_data
extant
setwd("~/Box Sync/colliding ranges/Simulations_humans/Results/available daily summaries")
details <- file.info(list.files())

trimmed_details <- details[which(list.files() == list.files(pattern = "Four_model_compare_results_extinct*")),]
ord <- order(trimmed_details$mtime, decreasing = TRUE)
rownames(trimmed_details[ord,])[1]
load(rownames(trimmed_details[ord,])[1])
extinct <- Concatenated_data

trimmed_details <- details[which(list.files() != list.files(pattern = "Four_model_compare_results_extinct*")),]
ord <- order(trimmed_details$mtime, decreasing = TRUE)
rownames(trimmed_details[ord,])[1]
load(rownames(trimmed_details[ord,])[1])
extant <- Concatenated_data
dim(extinct)
dim(extant)
for(i in c(9,10,11,12,14,15,16,17,19,20,21,22,24,25,26,27,29,30,31,32)){
    extinct[which(is.nan(as.numeric(as.character(extinct[, i]))) == TRUE), i] <- NA
}

for(i in c(9,10,11,12,14,15,16,17,19,20,21,22,24,25,26,27,29,30,31,32)){
    extant[which(is.nan(as.numeric(as.character(extant[, i]))) == TRUE), i] <- NA
}

i <- 19
for(i in c(20,21,24,25,26,27)){
    extinct[which(as.numeric(as.character(extinct[, i])) == 0), i] <- NA
}

for(i in c(20,21,24,25,26,27)){
    extant[which(as.numeric(as.character(extant[, i])) == 0), i] <- NA
}


xlimit <- c(0,1)
ylimit <- c(0,600)
maincex <- 0.9

png(file="Global_success_rate_per_parameter.png", width=8.5, height=11, units="in", res=300)

par(mfrow=c(5,4), mar=c(3,3,3,0))


hist(as.numeric(as.character(extinct[,9])), main="speciation of F in F env", col=adjustcolor("firebrick", alpha=0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex)
hist(as.numeric(as.character(extant[,9])), main="speciation of F in F env", col=adjustcolor("cornflowerblue", alpha=0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex, add=TRUE)


hist(as.numeric(as.character(extinct[,10])), main="speciation of D in F env", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex)
hist(as.numeric(as.character(extant[,10])), main="speciation of D in F env", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex, add=TRUE)


hist(as.numeric(as.character(extinct[,11])), main="speciation of F in D env", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex)
hist(as.numeric(as.character(extant[,11])), main="speciation of F in D env", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex, add=TRUE)

hist(as.numeric(as.character(extinct[,12])), main="speciation of D in D env", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex)
hist(as.numeric(as.character(extant[,12])), main="speciation of D in D env", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex, add=TRUE)

#######

hist(as.numeric(as.character(extinct[, 14])), main="extinction of F in F env", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex)
hist(as.numeric(as.character(extant[, 14])), main="extinction of F in F env", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex, add=TRUE)



hist(as.numeric(as.character(extinct[, 15])), main="extinction of D in F env", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex)
hist(as.numeric(as.character(extant[, 15])), main="extinction of D in F env", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex, add=TRUE)

hist(as.numeric(as.character(extinct[, 16])), main="extinction of F in D env", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex)
hist(as.numeric(as.character(extant[, 16])), main="extinction of F in D env", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex, add=TRUE)

hist(as.numeric(as.character(extinct[, 17])), main="extinction of D in D env", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex)
hist(as.numeric(as.character(extant[, 17])), main="extinction of D in D env", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex, add=TRUE)

######

hist(as.numeric(as.character(extinct[, 29])), main="arisal of F in F env", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex)
hist(as.numeric(as.character(extant[, 29])), main="arisal of F in F env", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex, add=TRUE)



hist(as.numeric(as.character(extinct[, 30])), main="arisal of D in F env", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex)
hist(as.numeric(as.character(extant[, 30])), main="arisal of D in F env", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex, add=TRUE)

hist(as.numeric(as.character(extinct[, 31])), main="arisal of F in D env", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex)
hist(as.numeric(as.character(extant[, 31])), main="arisal of F in D env", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex, add=TRUE)

hist(as.numeric(as.character(extinct[, 32])), main="arisal of D in D env", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex)
hist(as.numeric(as.character(extant[, 32])), main="arisal of D in D env", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex, add=TRUE)

######

hist(as.numeric(as.character(extinct[, 19])), main="NOPE -- Diffusion: source F, target F", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= c(0,18000), cex.main= maincex)
hist(as.numeric(as.character(extant[, 19])), main="NOPE -- Diffusion: source F, target F", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= c(0,18000), cex.main= maincex, add=TRUE)



hist(as.numeric(as.character(extinct[, 20])), main="Diffusion: source D, target F", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex)
hist(as.numeric(as.character(extant[, 20])), main="Diffusion: source D, target F", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex, add=TRUE)

hist(as.numeric(as.character(extinct[, 21])), main="Diffusion: source F, target D", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex)
hist(as.numeric(as.character(extant[, 21])), main="Diffusion: source F, target D", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex, add=TRUE)

hist(as.numeric(as.character(extinct[, 22])), main="NOPE -- Diffusion: source D, target D", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= c(0,18000), cex.main= maincex)
hist(as.numeric(as.character(extant[, 22])), main="NOPE -- Diffusion: source D, target D", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= c(0,18000), cex.main= maincex, add=TRUE)

####

hist(as.numeric(as.character(extinct[, 24])), main="Takeover: source F, target F", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex)
hist(as.numeric(as.character(extant[, 24])), main="Takeover: source F, target F", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex, add=TRUE)



hist(as.numeric(as.character(extinct[, 25])), main="Takeover: source D, target F", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex)
hist(as.numeric(as.character(extant[, 25])), main="Takeover: source D, target F", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex, add=TRUE)

hist(as.numeric(as.character(extinct[, 26])), main="Takeover: source F, target D", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex)
hist(as.numeric(as.character(extant[, 26])), main="Takeover: source F, target D", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex, add=TRUE)

hist(as.numeric(as.character(extinct[, 27])), main="Takeover: source D, target D", col=adjustcolor("firebrick", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex)
hist(as.numeric(as.character(extant[, 27])), main="Takeover: source D, target D", col=adjustcolor("cornflowerblue", alpha= 0.7), breaks=100, border=NA, xlim= xlimit, ylim= ylimit, cex.main= maincex, add=TRUE)


dev.off()
png(file="extiction minus extant per outcome.png", width=8.5, height=11, units="in", res=300)
par(mfrow=c(3,1))

plot(as.numeric(as.character(extinct[,9])), as.numeric(as.character(extinct[,14])), xlab="speciation", ylab="extinction", col= adjustcolor("firebrick", alpha=0.2), pch=19, cex=0.6, ylim=c(0,1))
plot(as.numeric(as.character(extant[,9])), as.numeric(as.character(extant[,14])), xlab="speciation", ylab="extinction", col= adjustcolor("cornflowerblue", alpha=0.2), pch=19, cex=0.6, ylim=c(0,1))

plot(as.numeric(as.character(extinct[,9])), as.numeric(as.character(extinct[,14])), xlab="speciation", ylab="extinction", col= adjustcolor("firebrick", alpha=0.2), pch=19, cex=0.6, ylim=c(0,1))
points(as.numeric(as.character(extant[,9])), as.numeric(as.character(extant[,14])), xlab="speciation", ylab="extinction", col= adjustcolor("cornflowerblue", alpha=0.2), pch=19, cex=0.6)


dev.off()
params <- extant[,-1:-35]
names(params)
break_number <- 10
xmin <-
xmax <- 

x1 <- as.numeric(params[,1])
h1 <- hist(x1,  plot=FALSE, breaks= break_number)
xfit1 <- seq(xmin, xmax, length= 100)
yfit1 <- dnorm(xfit1, mean=mean(x1), sd=sd(x1))
yfit1 <- yfit1*diff(h1$mids[1:2])*length(x1)+101.5
polygon(xfit1, yfit1, col=adjustcolor("limegreen", alpha=0.5), lwd=2, border=adjustcolor("limegreen", alpha=0.6))

Run a single random forest on available outputs

setwd("~/Box Sync/colliding ranges/Simulations_humans/Results/available daily summaries")
details <- file.info(list.files())

trimmed_details <- details[which(list.files() == list.files(pattern = "Four_model_compare_results_extinct*")),]
ord <- order(trimmed_details$mtime, decreasing = TRUE)
rownames(trimmed_details[ord,])[1]
load(rownames(trimmed_details[ord,])[1])
extinct <- Concatenated_data

trimmed_details <- details[which(list.files() != list.files(pattern = "Four_model_compare_results_extinct*")),]
ord <- order(trimmed_details$mtime, decreasing = TRUE)
rownames(trimmed_details[ord,])[1]
load(rownames(trimmed_details[ord,])[1])
extant <- Concatenated_data



load('~/Box Sync/colliding ranges/Simulations_humans/Available trees/real.analysis.RData')

Concatenated_data <- extant
head(Concatenated_data)
#Concatenated_data <- Concatenated_data[Concatenated_data[, 2] == "stats.no.bTO", ]
#Concatenated_data <- Concatenated_data[Concatenated_data[, 6] != "05", ]
# Concatenated_data[, 6] <- as.numeric(Concatenated_data[, 6])
# # Concatenated_data[original[, 2] == "background_takeover", 6] <-  Concatenated_data[original[, 2] == "background_takeover", 6] + 4
Concatenated_data[, 6] <- factor(Concatenated_data[, 6])
#head(Concatenated_data)
#names(Concatenated_data)

PCAdata <- Concatenated_data[, -(1:35)]
PCAdata <- PCAdata[, -12]
PCAdata <- apply(PCAdata, 2, as.numeric)
remove <- apply(is.na(PCAdata), 1, any)
PCAdata <- PCAdata[!remove, ]

# Predictions
library(randomForest)

data.analysis.comp2 <- data.frame("Model" = as.factor(Concatenated_data[!remove, 6]),
                                  PCAdata)
data.analysis.comp2$sprate <- data.analysis.comp2$trait_1_speciation/data.analysis.comp2$trait_2_speciation
data.analysis.comp2$extrate <- data.analysis.comp2$trait_1_extinction/data.analysis.comp2$trait_2_extinction


#load("Real_phy/real.analysis.RData")
a <- as.data.frame(real.analysis$results_summary_of_single_value_outputs)
a$sprate <- a$trait_1_speciation / a$trait_2_speciation
a$extrate <- a$trait_1_extinction / a$trait_2_extinction

data.analysis.comp3 <- data.analysis.comp2[, -c(2, 13:14, 16:20)]
#data.analysis.comp3 <- data.analysis.comp3[data.analysis.comp3$Model %in% 1:4, ]
#data.analysis.comp3$Model <- factor(data.analysis.comp3$Model)
#sub <- unlist(lapply(as.list(c(1:4)), function(x, y) {
#  sample(which(y$Model == x), min(table(data.analysis.comp3$Model)))},
#  y = data.analysis.comp3))
# data.analysis.comp3 <- data.analysis.comp3[sub, ]
fun <- function(x, y, per = .33) {sample(which(y$Model == x), round(table(y$Model)[1]*per))}

sub.test <- unlist(lapply(as.list(paste0(0, c(1:4))), fun,
                          y = data.analysis.comp3))
test2 <- data.analysis.comp3[sub.test, 2:ncol(data.analysis.comp3)]
test1 <- data.analysis.comp3[sub.test, 1]
train <- data.analysis.comp3[-sub.test, ]

train[, -1] <- apply(train[, -1], 2, as.numeric)
test2 <- as.data.frame(apply(test2, 2, as.numeric))
infinites <- which(apply(train[, -1], 2, is.infinite), arr.ind=T)
if (nrow(infinites) > 0) {
train <- train[-infinites[, 1], ]
}
infinites2 <- which(apply(test2, 2, is.infinite), arr.ind=T)
if (nrow(infinites2) > 0) {
test2 <- test2[-infinites2[, 1], ]
test1 <- test1[-infinites2[, 1]]
}


for(i in 1:100){
(fit <- randomForest(Model ~ ., data=train, xtest = test2, ytest = test1, 
                    importance=TRUE, ntree=1000, keep.forest = TRUE, replace=FALSE))

predictions <- predict(fit, 
                       a,
                       type="prob")
predictions

save(fit, file=paste0("~/Box Sync/colliding ranges/Simulations_humans/Results/RF_daily_output/RF_daily_output_", format(Sys.time(), format="%d_%b_%Y"), "_",i, "_NoREPLACEMENT_.Rdata"))
}
save(fit, file=paste0("~/Box Sync/colliding ranges/Simulations_humans/Results/RF_daily_output/RF_daily_output_", format(Sys.time(), format="%d_%b_%Y"),".Rdata"))

Visualize outputs from Random Forest analysis

plot(fit, ylim=c(0,1))
labs <- c("Basic", "+Diffusion", "+Takeover", "+Diffusion +Takeover")
# bar plot
png("Prob_aus.png", width = 25, height = 25, res = 300, units = "in")
par(mar = c(8, 8, 1, 1))
pred <- setNames(as.numeric(predictions), labs)
cols <- rev(c("darkgreen", "red", "blue", "darkorange1"))
barplot(pred, col = cols, ylab = "Proability", cex.lab = 3, cex.names = 2)
dev.off()
# Plot confusion matrix
png("Conffusion_matrix_all.png", width = 25, height = 25, res=300, units="in")
par(mar = c(10, 11, 1, 1))
colors1 <- colorRampPalette(colors = c("#f0f0f0", "#bdbdbd","#636363"))
prop <- apply(fit$confusion[, -5], 2, function(x){x / sum(x)}) * 100

image(prop, col = colors1(20), axes=FALSE)
axis(1, at=c(0, .33, .66, 1), labels=labs, tick = FALSE, line = FALSE, cex.axis = 3.5, pos = -.19)
axis(2, at=c(0, .33, .66, 1), labels=labs, tick = FALSE, line = FALSE, cex.axis = 3.5)
mtext("ACTUAL", side = 1, padj = 3, cex = 4)
mtext("PREDICTED", side = 2, padj = -3, cex = 4)

for(i in 1:4) {
  for(j in 1:4) {
    text(x = c(0, .33, .66, 1)[i], y = c(0, .33, .66, 1)[j], paste0(round(prop[i, j], 2), "%"),
         cex = 5)
  }
}
dev.off()
importance(fit)
# Variables importance

imp <- importance(fit)
imp <- apply(imp, 2, function(x) (x - min(x))/(max(x) - min(x)))
imp <- imp[sort(imp[, 5], index.return = TRUE, decreasing = TRUE)$ix, ]


names <- rownames(imp)
names[names == "spatial.tests.fora"] <- "Space F"
names[names == "spatial.tests.dom"] <- "Space D"
names[names == "sprate"] <- "Sp(ratio)"
names[names == "transition_from_trait_1_to_2"] <- "TR(1-2)"
names[names == "transition_from_trait_2_to_1"] <- "TR(2-1)"
names[names == "Phylogenetic_signal"] <- "PhySig(D)"
names[names == "Evolutionary_distinctiveness_sum"] <- "EDsum"
names[names == "Pylo_diversity_is_sum_of_BL"] <- "PDsum"
names[names == "transition_rate_ratio_1to2_over_2to1"] <- "TR(ratio)"
names[names == "gamma"] <- "Gamma"
names[names == "mean_Phylogenetic_isolation"] <- "MPI"
names[names == "extrate"] <- "Ext(ratio)"
names[names == "average_phylogenetic_diversity_is_mean_of_BL"] <- "PDmean"
names[names == "extinction_per_speciation"] <- "DR"
names[names == "variance_Phylogenetic_isolation"] <- "VPI"
names[names == "F_quadratic_entropy_is_sum_of_PD"] <- "F"
names[names == "Mean_pairwise_distance"] <- "MPD"
names[names == "variance_Pylo_diversity_is_variance_of_BL"] <- "PDvar"
names[names == "variance_pairwise_distance"] <- "VPD"


png("var_import_all.png", width = 25, height = 25, unit="in", res=300)
par(mar = c(10, 18, 1, 1))
plot(x = rev(imp[, 5]), y = 1:nrow(imp), type = "l", yaxt = "n", 
     ylab = "", xlab = "Variable Importance",
     xlim = c(0, 1), lwd = 2, cex.lab = 4)
for (i in 1:nrow(imp)) {
  abline(h = i, lty = 3, col = "gray80")
}
abline(v = seq(0, 1, 1/19), lty = 3, col = "gray80")

lines(x = rev(imp[, 4]), y = 1:nrow(imp), col = "darkgreen", lwd = 2)
lines(x = rev(imp[, 3]), y = 1:nrow(imp), col = "red", lwd = 2)
lines(x = rev(imp[, 2]), y = 1:nrow(imp), col = "blue", lwd = 2)
lines(x = rev(imp[, 1]), y = 1:nrow(imp), col = "darkorange1", lwd = 2)
lines(x = rev(imp[, 5]), y = 1:nrow(imp), lwd = 3)

points(x = rev(imp[, 4]), y = 1:nrow(imp), col = "darkgreen", cex = 2)
points(x = rev(imp[, 3]), y = 1:nrow(imp), col = "red", cex = 2)
points(x = rev(imp[, 2]), y = 1:nrow(imp), col = "blue", cex = 2)
points(x = rev(imp[, 1]), y = 1:nrow(imp), col = "darkorange1", cex = 2)
points(x = rev(imp[, 5]), y = 1:nrow(imp), pch = 20, cex = 3)


text(y = 1:nrow(imp), x = par("usr")[1] - .17, labels = rev(names),
     srt = 0, pos = 4, xpd = T, cex = 4)
dev.off()
par(mfrow=c(2,3))

# Box plots
boxplot(spatial.tests.fora ~ Model, data = data.analysis.comp3)
abline(h = a$spatial.tests.fora, col = "red", lty = 2)

boxplot(spatial.tests.dom ~ Model, data = data.analysis.comp3)
abline(h = a$spatial.tests.fora, col = "red", lty = 2)

boxplot(log(sprate) ~ Model, data = data.analysis.comp3, ylim = c(-10, 10))
abline(h = log(a$sprate), col = "red", lty = 2)

boxplot(log(extrate) ~ Model, data = data.analysis.comp3, ylim = c(-10, 10))
abline(h = log(a$extrate), col = "red", lty = 2)

boxplot(log(transition_rate_ratio_1to2_over_2to1) ~ Model, data = data.analysis.comp3)
abline(h = log(a$sprate), col = "red", lty = 2)

boxplot(Phylogenetic_signal ~ Model, data = data.analysis.comp3, ylim = c(0, 1))
abline(h = a$Phylogenetic_signal, col = "red", lty = 2)
#build a data tracking table to track parameter changes through time

str(fit)

y
LS0tCnRpdGxlOiAnRC1wbGFjZSBGQVJNIGRvY3VtZW50YXRpb246IE1vZHVsZSAzJwphdXRob3I6ICJUeSBUdWZmLCBCcnVubyBWaWxlbGEsIGFuZCBDYXJsb3MgQm90ZXJvIgpkYXRlOiAncHJvamVjdCBiZWdhbjogMTUgTWF5IDIwMTYsIGRvY3VtZW50IHVwZGF0ZWQ6IGByIHN0cmZ0aW1lKFN5cy50aW1lKCksIGZvcm1hdAogID0gIiVkICVCICVZIilgJwpvdXRwdXQ6CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQKICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0CmJpYmxpb2dyYXBoeTogRkFSTSBwYWNrYWdlLmJpYgotLS0KCiMgTW9kdWxlIDM6IEFuYWx5c2luZyByZXN1bHRzIHByb2R1Y2UgZnJvbSBNb2R1bGVzIDEgYW5kIDIKCmBgYHtyfQpsaWJyYXJ5KHBuZykKYGBgCgoKIyMgQ29uc29saWRhdGUgYXZhaWxhYmxlIGZpbGVzIGludG8gYSBzaW5nbGUgdGFibGUKYGBge3IgZXZhbD1GQUxTRX0KIyMgRmlyc3QgY29uc29saWRhdGUgdGhlIGF2YWlsYWJsZSBmaWxlcyBpbnRvIGEgc2luZ2xlIHRhYmxlCiAgICAKICAgICAgcGF0aCA8LSAifi9Cb3ggU3luYy9Gb3VyIG1vZGVsIGNvbXBhcmUvTW9kdWxlIDIiCiAgICAgICAgICAgCiAgICAgCiAgICAgICAgICAgc2V0d2QocGF0aCkKICAgIG15ZmlsZXNfZnVsbCA8LSBsaXN0LmRpcnMoKQogICAgYW5hbHl6ZV90aGlzX21hbnkgPC0gbGVuZ3RoKG15ZmlsZXNfZnVsbCkKICAgIAogICAgYXZhaWxhYmxlX2ZpbGVzIDwtIG1hdHJpeChOQSwgMSwgMSkKICAgIAogICAgICAgIAogICAgZm9yKGkgaW4gMTogYW5hbHl6ZV90aGlzX21hbnkpewogICAgYXZhaWxhYmxlX2ZpbGVzIDwtIHJiaW5kKGF2YWlsYWJsZV9maWxlcyAsIGFzLm1hdHJpeChsaXN0LmZpbGVzKG15ZmlsZXNfZnVsbFtpXSwgZnVsbC5uYW1lcyA9IFRSVUUpKSkKICAgIH0KICAgIGRpbShhdmFpbGFibGVfZmlsZXMpCiAgICAKICAgIHNwbGl0LmZpbGUubmFtZSA8LSBzdHJzcGxpdChhdmFpbGFibGVfZmlsZXNbMTBdLCBzcGxpdCA9ICJfIikgCiAgICAKICAgIAogICAgCiAKYXZhaWxhYmxlIDwtIGxpc3QuZmlsZXMoKQpmaWxlcyA8LSBtYXRyaXgocmVwKE5BLCA2MiksIGxlbmd0aChhdmFpbGFibGUpLCA2MikKZGltKGZpbGVzKQppIDwtIDEwCgoKZm9yKGkgaW4gMTpsZW5ndGgoYXZhaWxhYmxlKSl7CmxvYWQoYXZhaWxhYmxlW2ldKQpuYW1lIDwtIHVubGlzdChzdHJzcGxpdChhdmFpbGFibGVbaV0sIHNwbGl0PSJfIikpCmZpbGVzW2ksXSA8LSBjKGFzLnZlY3RvcihtYXRyaXgobmFtZSwgMSwzNSkpLG1hdHJpeChTaW1fc3RhdGlzdGljc1tbMV1dLCAxLCAyNykpCgp9CgoKY29sbmFtZXMoZmlsZXMpIDwtICBjKAoKCU5BLAoJImJhY2tncm91bmRfdGFrZW92ZXJfdHlwZSIgLAoJTkEsCgkicmVwbGljYXRlIiwKCU5BLAoJIk1vZGVsX3R5cGUiLAoJcmVwKE5BLDIpLAoJInNwZWNpYXRpb25fb2ZfRW52X05vbkQiLAoJInNwZWNpYXRpb25fb2ZfRW52X0QiLAoJInNwZWNpYXRpb25fb2ZfRm9yIiwKCSJzcGVjaWF0aW9uX29mX0RvbSIsCglOQSwKCSJleHRpbmN0aW9uX29mX0Vudl9Ob25EIiwKCSJleHRpbmN0aW9uX29mX0Vudl9EIiwKCSJleHRpbmN0aW9uX29mX0ZvciIsCgkiZXh0aW5jdGlvbl9vZl9Eb20iLAoJTkEsCgkiUC5kaWZmdXNpb25fVGFyZ2V0X2ZvcmFnZXIiLAoJIlAuZGlmZnVzaW9uX1RhcmdldF9kb21lc3RpY2F0b3IiLAoJIlAuZGlmZnVzaW9uX1NvdXJjZV9mb3JhZ2VyIiwKCSJQLmRpZmZ1c2lvbl9Tb3VyY2VfZG9tZXN0aWNhdG9yIiwKCU5BLAoJIlAudGFrZW92ZXJfVGFyZ2V0X2ZvcmFnZXIiLAoJIlAudGFrZW92ZXJfVGFyZ2V0X2RvbWVzdGljYXRvciIsCgkiUC50YWtlb3Zlcl9Tb3VyY2VfZm9yYWdlciIsCgkiUC50YWtlb3Zlcl9Tb3VyY2VfZG9tZXN0aWNhdG9yIiwKCU5BLAoJImFyaXNhbF9vZl9FbnZfTm9uRCIsCgkiYXJpc2FsX29mX0Vudl9EIiwKCSJhcmlzYWxfb2ZfRm9yIiwKCSJhcmlzYWxfb2ZfRG9tIiwKCQoJTkEsIAoJInRpbWVzdGVwcyIsIAoJTkEsCiAgICAgICAgCiAgICAibnVtYmVyX29mX2JyYW5jaGVzIiwKCSJQeWxvX2RpdmVyc2l0eV9pc19zdW1fb2ZfQkwiLAoJImF2ZXJhZ2VfcGh5bG9nZW5ldGljX2RpdmVyc2l0eV9pc19tZWFuX29mX0JMIiwKCSJ2YXJpYW5jZV9QeWxvX2RpdmVyc2l0eV9pc192YXJpYW5jZV9vZl9CTCIsCgoJIkZfcXVhZHJhdGljX2VudHJvcHlfaXNfc3VtX29mX1BEIiwKCSJNZWFuX3BhaXJ3aXNlX2Rpc3RhbmNlIiwKCSJ2YXJpYW5jZV9wYWlyd2lzZV9kaXN0YW5jZSIsCgoJIkV2b2x1dGlvbmFyeV9kaXN0aW5jdGl2ZW5lc3Nfc3VtIiwKCSJtZWFuX1BoeWxvZ2VuZXRpY19pc29sYXRpb24iLAoJInZhcmlhbmNlX1BoeWxvZ2VuZXRpY19pc29sYXRpb24iLAoKCSJnYW1tYSIsCgkiZ2FtbWFfcF92YWx1ZSIsCgkic3BlY2lhdGlvbl9yYXRlIiwKCSJleHRpbmN0aW9uX3JhdGUiLAoJImV4dGluY3Rpb25fcGVyX3NwZWNpYXRpb24iLAoJInNwZWNpYXRpb25fbWludXNfZXh0aW5jdGlvbiIsCgkidHJhaXRfMV9zcGVjaWF0aW9uIiwKICAJInRyYWl0XzJfc3BlY2lhdGlvbiIgLAogIAkidHJhaXRfMV9leHRpbmN0aW9uIiAsCiAgCSJ0cmFpdF8yX2V4dGluY3Rpb24iICwKICAJInRyYW5zaXRpb25fZnJvbV90cmFpdF8xX3RvXzIiICwKICAJInRyYW5zaXRpb25fZnJvbV90cmFpdF8yX3RvXzEiICwKICAJInRyYW5zaXRpb25fcmF0ZV9yYXRpb18xdG8yX292ZXJfMnRvMSIgLAogIAkiUGh5bG9nZW5ldGljX3NpZ25hbCIsCiAgCSJzcGF0aWFsLnRlc3RzLmZvcmEiLAogIAkic3BhdGlhbC50ZXN0cy5kb20iLAogIAkicHJldmFsZW5jZSIKICAJCiAgICAKICApCgpyZXN1bHRzX3RhYmxlIDwtIGFzLmRhdGEuZnJhbWUoZmlsZXMpCmhlYWQocmVzdWx0c190YWJsZSkKZGltKHJlc3VsdHNfdGFibGUpCkNvbmNhdGVuYXRlZF9kYXRhIDwtIHJlc3VsdHNfdGFibGUKc2F2ZShDb25jYXRlbmF0ZWRfZGF0YSwgZmlsZT0ifi9EZXNrdG9wL0ZvdXJfbW9kZWxfY29tcGFyZV9yZXN1bHRzLlJkYXRhIikKCm9uZSA8LSBzdWJzZXQocmVzdWx0c190YWJsZSwgTW9kZWxfdHlwZT09IjAxIiApCnR3byA8LSBzdWJzZXQocmVzdWx0c190YWJsZSwgTW9kZWxfdHlwZT09IjAyIiApCnRocmVlIDwtIHN1YnNldChyZXN1bHRzX3RhYmxlLCBNb2RlbF90eXBlPT0iMDMiICkKZm91ciA8LSBzdWJzZXQocmVzdWx0c190YWJsZSwgTW9kZWxfdHlwZT09IjA0IiApCmNyb3AgPC0gbWluKGxlbmd0aChvbmVbLDFdKSwKbGVuZ3RoKHR3b1ssMV0pLApsZW5ndGgodGhyZWVbLDFdKSwKbGVuZ3RoKGZvdXJbLDFdKSkKb25lIDwtIG9uZVsxOmNyb3AsXQp0d28gPC0gdHdvWzE6Y3JvcCxdCnRocmVlIDwtIHRocmVlWzE6Y3JvcCxdCmZvdXIgPC0gZm91clsxOmNyb3AsXQoKQ29uY2F0ZW5hdGVkX2RhdGEgPC0gcmJpbmQob25lLCB0d28sIHRocmVlLCBmb3VyKQpkaW0oQ29uY2F0ZW5hdGVkX2RhdGEpCgoKCgoKc2F2ZShDb25jYXRlbmF0ZWRfZGF0YSwgZmlsZT1wYXN0ZTAoIn4vQm94IFN5bmMvY29sbGlkaW5nIHJhbmdlcy9TaW11bGF0aW9uc19odW1hbnMvUmVzdWx0cy9hdmFpbGFibGUgZGFpbHkgc3VtbWFyaWVzL0ZvdXJfbW9kZWxfY29tcGFyZV9yZXN1bHRzIiwgZm9ybWF0KFN5cy50aW1lKCksIGZvcm1hdD0iJWRfJWJfJVkiKSwiX2Nyb3BfdG9fIiwgY3JvcCwiLlJkYXRhIikpCmNyb3AKCmBgYAoKCgoKYGBge3IgZXZhbD1GQUxTRX0KIyMgRmlyc3QgY29uc29saWRhdGUgdGhlIGF2YWlsYWJsZSBmaWxlcyBpbnRvIGEgc2luZ2xlIHRhYmxlCiAgICAKICAgICAgcGF0aCA8LSAifi9Cb3ggU3luYy9Gb3VyIG1vZGVsIGNvbXBhcmUvTW9kdWxlIDIgZXh0aW5jdCIKICAgICAgICAgICAKICAgICAKICAgICAgICAgICBzZXR3ZChwYXRoKQogICAgbXlmaWxlc19mdWxsIDwtIGxpc3QuZGlycygpCiAgICBhbmFseXplX3RoaXNfbWFueSA8LSBsZW5ndGgobXlmaWxlc19mdWxsKQogICAgCiAgICBhdmFpbGFibGVfZmlsZXMgPC0gbWF0cml4KE5BLCAxLCAxKQogICAgCiAgICAgICAgCiAgICBmb3IoaSBpbiAxOiBhbmFseXplX3RoaXNfbWFueSl7CiAgICBhdmFpbGFibGVfZmlsZXMgPC0gcmJpbmQoYXZhaWxhYmxlX2ZpbGVzICwgYXMubWF0cml4KGxpc3QuZmlsZXMobXlmaWxlc19mdWxsW2ldLCBmdWxsLm5hbWVzID0gVFJVRSkpKQogICAgfQogICAgZGltKGF2YWlsYWJsZV9maWxlcykKICAgIAogICAgc3BsaXQuZmlsZS5uYW1lIDwtIHN0cnNwbGl0KGF2YWlsYWJsZV9maWxlc1sxMF0sIHNwbGl0ID0gIl8iKSAKICAgIAogICAgCiAgICAKIAphdmFpbGFibGUgPC0gbGlzdC5maWxlcygpCmZpbGVzIDwtIG1hdHJpeChyZXAoTkEsIDYyKSwgbGVuZ3RoKGF2YWlsYWJsZSksIDYyKQpkaW0oZmlsZXMpCmkgPC0gMTAKCgpmb3IoaSBpbiAxOmxlbmd0aChhdmFpbGFibGUpKXsKbG9hZChhdmFpbGFibGVbaV0pCm5hbWUgPC0gdW5saXN0KHN0cnNwbGl0KGF2YWlsYWJsZVtpXSwgc3BsaXQ9Il8iKSkKZmlsZXNbaSxdIDwtIGMoYXMudmVjdG9yKG1hdHJpeChuYW1lLCAxLDM1KSksbWF0cml4KFNpbV9zdGF0aXN0aWNzW1sxXV0sIDEsIDI3KSkKCn0KCgpjb2xuYW1lcyhmaWxlcykgPC0gIGMoCgoJTkEsCgkiYmFja2dyb3VuZF90YWtlb3Zlcl90eXBlIiAsCglOQSwKCSJyZXBsaWNhdGUiLAoJTkEsCgkiTW9kZWxfdHlwZSIsCglyZXAoTkEsMiksCgkic3BlY2lhdGlvbl9vZl9FbnZfTm9uRCIsCgkic3BlY2lhdGlvbl9vZl9FbnZfRCIsCgkic3BlY2lhdGlvbl9vZl9Gb3IiLAoJInNwZWNpYXRpb25fb2ZfRG9tIiwKCU5BLAoJImV4dGluY3Rpb25fb2ZfRW52X05vbkQiLAoJImV4dGluY3Rpb25fb2ZfRW52X0QiLAoJImV4dGluY3Rpb25fb2ZfRm9yIiwKCSJleHRpbmN0aW9uX29mX0RvbSIsCglOQSwKCSJQLmRpZmZ1c2lvbl9UYXJnZXRfZm9yYWdlciIsCgkiUC5kaWZmdXNpb25fVGFyZ2V0X2RvbWVzdGljYXRvciIsCgkiUC5kaWZmdXNpb25fU291cmNlX2ZvcmFnZXIiLAoJIlAuZGlmZnVzaW9uX1NvdXJjZV9kb21lc3RpY2F0b3IiLAoJTkEsCgkiUC50YWtlb3Zlcl9UYXJnZXRfZm9yYWdlciIsCgkiUC50YWtlb3Zlcl9UYXJnZXRfZG9tZXN0aWNhdG9yIiwKCSJQLnRha2VvdmVyX1NvdXJjZV9mb3JhZ2VyIiwKCSJQLnRha2VvdmVyX1NvdXJjZV9kb21lc3RpY2F0b3IiLAoJTkEsCgkiYXJpc2FsX29mX0Vudl9Ob25EIiwKCSJhcmlzYWxfb2ZfRW52X0QiLAoJImFyaXNhbF9vZl9Gb3IiLAoJImFyaXNhbF9vZl9Eb20iLAoJCglOQSwgCgkidGltZXN0ZXBzIiwgCglOQSwKICAgICAgICAKICAgICJudW1iZXJfb2ZfYnJhbmNoZXMiLAoJIlB5bG9fZGl2ZXJzaXR5X2lzX3N1bV9vZl9CTCIsCgkiYXZlcmFnZV9waHlsb2dlbmV0aWNfZGl2ZXJzaXR5X2lzX21lYW5fb2ZfQkwiLAoJInZhcmlhbmNlX1B5bG9fZGl2ZXJzaXR5X2lzX3ZhcmlhbmNlX29mX0JMIiwKCgkiRl9xdWFkcmF0aWNfZW50cm9weV9pc19zdW1fb2ZfUEQiLAoJIk1lYW5fcGFpcndpc2VfZGlzdGFuY2UiLAoJInZhcmlhbmNlX3BhaXJ3aXNlX2Rpc3RhbmNlIiwKCgkiRXZvbHV0aW9uYXJ5X2Rpc3RpbmN0aXZlbmVzc19zdW0iLAoJIm1lYW5fUGh5bG9nZW5ldGljX2lzb2xhdGlvbiIsCgkidmFyaWFuY2VfUGh5bG9nZW5ldGljX2lzb2xhdGlvbiIsCgoJImdhbW1hIiwKCSJnYW1tYV9wX3ZhbHVlIiwKCSJzcGVjaWF0aW9uX3JhdGUiLAoJImV4dGluY3Rpb25fcmF0ZSIsCgkiZXh0aW5jdGlvbl9wZXJfc3BlY2lhdGlvbiIsCgkic3BlY2lhdGlvbl9taW51c19leHRpbmN0aW9uIiwKCSJ0cmFpdF8xX3NwZWNpYXRpb24iLAogIAkidHJhaXRfMl9zcGVjaWF0aW9uIiAsCiAgCSJ0cmFpdF8xX2V4dGluY3Rpb24iICwKICAJInRyYWl0XzJfZXh0aW5jdGlvbiIgLAogIAkidHJhbnNpdGlvbl9mcm9tX3RyYWl0XzFfdG9fMiIgLAogIAkidHJhbnNpdGlvbl9mcm9tX3RyYWl0XzJfdG9fMSIgLAogIAkidHJhbnNpdGlvbl9yYXRlX3JhdGlvXzF0bzJfb3Zlcl8ydG8xIiAsCiAgCSJQaHlsb2dlbmV0aWNfc2lnbmFsIiwKICAJInNwYXRpYWwudGVzdHMuZm9yYSIsCiAgCSJzcGF0aWFsLnRlc3RzLmRvbSIsCiAgCSJwcmV2YWxlbmNlIgogIAkKICAgIAogICkKCkNvbmNhdGVuYXRlZF9kYXRhIDwtIGFzLmRhdGEuZnJhbWUoZmlsZXMpCmhlYWQoQ29uY2F0ZW5hdGVkX2RhdGEpCmRpbShDb25jYXRlbmF0ZWRfZGF0YSkKCnNhdmUoQ29uY2F0ZW5hdGVkX2RhdGEsIGZpbGU9cGFzdGUwKCJ+L0JveCBTeW5jL2NvbGxpZGluZyByYW5nZXMvU2ltdWxhdGlvbnNfaHVtYW5zL1Jlc3VsdHMvYXZhaWxhYmxlIGRhaWx5IHN1bW1hcmllcy9Gb3VyX21vZGVsX2NvbXBhcmVfcmVzdWx0c19leHRpbmN0XyIsIGZvcm1hdChTeXMudGltZSgpLCBmb3JtYXQ9IiVkXyViXyVZIiksIl9jcm9wX3RvXyIsIGNyb3AsIi5SZGF0YSIpKQoKYGBgCgoKIyMgU3VtbWFyaXplIG92ZXJhbGwgZXh0aW5jdGlvbiByYXRlcwpgYGB7ciBldmFsPUZBTFNFfQpsb2FkKCd+L0JveCBTeW5jL2NvbGxpZGluZyByYW5nZXMvU2ltdWxhdGlvbnNfaHVtYW5zL1Jlc3VsdHMvYXZhaWxhYmxlIGRhaWx5IHN1bW1hcmllcy9Gb3VyX21vZGVsX2NvbXBhcmVfcmVzdWx0c18wMl9NYXJfMjAxN19jcm9wX3RvXzM0ODEuUmRhdGEnKQpleHRhbnQgPC0gQ29uY2F0ZW5hdGVkX2RhdGEKZXh0YW50CmBgYAoKCgoKYGBge3IgZXZhbD1GQUxTRX0Kc2V0d2QoIn4vQm94IFN5bmMvY29sbGlkaW5nIHJhbmdlcy9TaW11bGF0aW9uc19odW1hbnMvUmVzdWx0cy9hdmFpbGFibGUgZGFpbHkgc3VtbWFyaWVzIikKZGV0YWlscyA8LSBmaWxlLmluZm8obGlzdC5maWxlcygpKQoKdHJpbW1lZF9kZXRhaWxzIDwtIGRldGFpbHNbd2hpY2gobGlzdC5maWxlcygpID09IGxpc3QuZmlsZXMocGF0dGVybiA9ICJGb3VyX21vZGVsX2NvbXBhcmVfcmVzdWx0c19leHRpbmN0KiIpKSxdCm9yZCA8LSBvcmRlcih0cmltbWVkX2RldGFpbHMkbXRpbWUsIGRlY3JlYXNpbmcgPSBUUlVFKQpyb3duYW1lcyh0cmltbWVkX2RldGFpbHNbb3JkLF0pWzFdCmxvYWQocm93bmFtZXModHJpbW1lZF9kZXRhaWxzW29yZCxdKVsxXSkKZXh0aW5jdCA8LSBDb25jYXRlbmF0ZWRfZGF0YQoKdHJpbW1lZF9kZXRhaWxzIDwtIGRldGFpbHNbd2hpY2gobGlzdC5maWxlcygpICE9IGxpc3QuZmlsZXMocGF0dGVybiA9ICJGb3VyX21vZGVsX2NvbXBhcmVfcmVzdWx0c19leHRpbmN0KiIpKSxdCm9yZCA8LSBvcmRlcih0cmltbWVkX2RldGFpbHMkbXRpbWUsIGRlY3JlYXNpbmcgPSBUUlVFKQpyb3duYW1lcyh0cmltbWVkX2RldGFpbHNbb3JkLF0pWzFdCmxvYWQocm93bmFtZXModHJpbW1lZF9kZXRhaWxzW29yZCxdKVsxXSkKZXh0YW50IDwtIENvbmNhdGVuYXRlZF9kYXRhCgoKCgoKYGBgCgpgYGB7ciBldmFsPUZBTFNFfQpkaW0oZXh0aW5jdCkKZGltKGV4dGFudCkKYGBgCgoKCgpgYGB7ciBldmFsPUZBTFNFfQoKZm9yKGkgaW4gYyg5LDEwLDExLDEyLDE0LDE1LDE2LDE3LDE5LDIwLDIxLDIyLDI0LDI1LDI2LDI3LDI5LDMwLDMxLDMyKSl7CglleHRpbmN0W3doaWNoKGlzLm5hbihhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRpbmN0WywgaV0pKSkgPT0gVFJVRSksIGldIDwtIE5BCn0KCmZvcihpIGluIGMoOSwxMCwxMSwxMiwxNCwxNSwxNiwxNywxOSwyMCwyMSwyMiwyNCwyNSwyNiwyNywyOSwzMCwzMSwzMikpewoJZXh0YW50W3doaWNoKGlzLm5hbihhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRhbnRbLCBpXSkpKSA9PSBUUlVFKSwgaV0gPC0gTkEKfQoKaSA8LSAxOQpmb3IoaSBpbiBjKDIwLDIxLDI0LDI1LDI2LDI3KSl7CglleHRpbmN0W3doaWNoKGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGluY3RbLCBpXSkpID09IDApLCBpXSA8LSBOQQp9Cgpmb3IoaSBpbiBjKDIwLDIxLDI0LDI1LDI2LDI3KSl7CglleHRhbnRbd2hpY2goYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoZXh0YW50WywgaV0pKSA9PSAwKSwgaV0gPC0gTkEKfQoKCnhsaW1pdCA8LSBjKDAsMSkKeWxpbWl0IDwtIGMoMCw2MDApCm1haW5jZXggPC0gMC45CgpwbmcoZmlsZT0iR2xvYmFsX3N1Y2Nlc3NfcmF0ZV9wZXJfcGFyYW1ldGVyLnBuZyIsIHdpZHRoPTguNSwgaGVpZ2h0PTExLCB1bml0cz0iaW4iLCByZXM9MzAwKQoKcGFyKG1mcm93PWMoNSw0KSwgbWFyPWMoMywzLDMsMCkpCgoKaGlzdChhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRpbmN0Wyw5XSkpLCBtYWluPSJzcGVjaWF0aW9uIG9mIEYgaW4gRiBlbnYiLCBjb2w9YWRqdXN0Y29sb3IoImZpcmVicmljayIsIGFscGhhPTAuNyksIGJyZWFrcz0xMDAsIGJvcmRlcj1OQSwgeGxpbT0geGxpbWl0LCB5bGltPSB5bGltaXQsIGNleC5tYWluPSBtYWluY2V4KQpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGFudFssOV0pKSwgbWFpbj0ic3BlY2lhdGlvbiBvZiBGIGluIEYgZW52IiwgY29sPWFkanVzdGNvbG9yKCJjb3JuZmxvd2VyYmx1ZSIsIGFscGhhPTAuNyksIGJyZWFrcz0xMDAsIGJvcmRlcj1OQSwgeGxpbT0geGxpbWl0LCB5bGltPSB5bGltaXQsIGNleC5tYWluPSBtYWluY2V4LCBhZGQ9VFJVRSkKCgpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGluY3RbLDEwXSkpLCBtYWluPSJzcGVjaWF0aW9uIG9mIEQgaW4gRiBlbnYiLCBjb2w9YWRqdXN0Y29sb3IoImZpcmVicmljayIsIGFscGhhPSAwLjcpLCBicmVha3M9MTAwLCBib3JkZXI9TkEsIHhsaW09IHhsaW1pdCwgeWxpbT0geWxpbWl0LCBjZXgubWFpbj0gbWFpbmNleCkKaGlzdChhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRhbnRbLDEwXSkpLCBtYWluPSJzcGVjaWF0aW9uIG9mIEQgaW4gRiBlbnYiLCBjb2w9YWRqdXN0Y29sb3IoImNvcm5mbG93ZXJibHVlIiwgYWxwaGE9IDAuNyksIGJyZWFrcz0xMDAsIGJvcmRlcj1OQSwgeGxpbT0geGxpbWl0LCB5bGltPSB5bGltaXQsIGNleC5tYWluPSBtYWluY2V4LCBhZGQ9VFJVRSkKCgpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGluY3RbLDExXSkpLCBtYWluPSJzcGVjaWF0aW9uIG9mIEYgaW4gRCBlbnYiLCBjb2w9YWRqdXN0Y29sb3IoImZpcmVicmljayIsIGFscGhhPSAwLjcpLCBicmVha3M9MTAwLCBib3JkZXI9TkEsIHhsaW09IHhsaW1pdCwgeWxpbT0geWxpbWl0LCBjZXgubWFpbj0gbWFpbmNleCkKaGlzdChhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRhbnRbLDExXSkpLCBtYWluPSJzcGVjaWF0aW9uIG9mIEYgaW4gRCBlbnYiLCBjb2w9YWRqdXN0Y29sb3IoImNvcm5mbG93ZXJibHVlIiwgYWxwaGE9IDAuNyksIGJyZWFrcz0xMDAsIGJvcmRlcj1OQSwgeGxpbT0geGxpbWl0LCB5bGltPSB5bGltaXQsIGNleC5tYWluPSBtYWluY2V4LCBhZGQ9VFJVRSkKCmhpc3QoYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoZXh0aW5jdFssMTJdKSksIG1haW49InNwZWNpYXRpb24gb2YgRCBpbiBEIGVudiIsIGNvbD1hZGp1c3Rjb2xvcigiZmlyZWJyaWNrIiwgYWxwaGE9IDAuNyksIGJyZWFrcz0xMDAsIGJvcmRlcj1OQSwgeGxpbT0geGxpbWl0LCB5bGltPSB5bGltaXQsIGNleC5tYWluPSBtYWluY2V4KQpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGFudFssMTJdKSksIG1haW49InNwZWNpYXRpb24gb2YgRCBpbiBEIGVudiIsIGNvbD1hZGp1c3Rjb2xvcigiY29ybmZsb3dlcmJsdWUiLCBhbHBoYT0gMC43KSwgYnJlYWtzPTEwMCwgYm9yZGVyPU5BLCB4bGltPSB4bGltaXQsIHlsaW09IHlsaW1pdCwgY2V4Lm1haW49IG1haW5jZXgsIGFkZD1UUlVFKQoKIyMjIyMjIwoKaGlzdChhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRpbmN0WywgMTRdKSksIG1haW49ImV4dGluY3Rpb24gb2YgRiBpbiBGIGVudiIsIGNvbD1hZGp1c3Rjb2xvcigiZmlyZWJyaWNrIiwgYWxwaGE9IDAuNyksIGJyZWFrcz0xMDAsIGJvcmRlcj1OQSwgeGxpbT0geGxpbWl0LCB5bGltPSB5bGltaXQsIGNleC5tYWluPSBtYWluY2V4KQpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGFudFssIDE0XSkpLCBtYWluPSJleHRpbmN0aW9uIG9mIEYgaW4gRiBlbnYiLCBjb2w9YWRqdXN0Y29sb3IoImNvcm5mbG93ZXJibHVlIiwgYWxwaGE9IDAuNyksIGJyZWFrcz0xMDAsIGJvcmRlcj1OQSwgeGxpbT0geGxpbWl0LCB5bGltPSB5bGltaXQsIGNleC5tYWluPSBtYWluY2V4LCBhZGQ9VFJVRSkKCgoKaGlzdChhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRpbmN0WywgMTVdKSksIG1haW49ImV4dGluY3Rpb24gb2YgRCBpbiBGIGVudiIsIGNvbD1hZGp1c3Rjb2xvcigiZmlyZWJyaWNrIiwgYWxwaGE9IDAuNyksIGJyZWFrcz0xMDAsIGJvcmRlcj1OQSwgeGxpbT0geGxpbWl0LCB5bGltPSB5bGltaXQsIGNleC5tYWluPSBtYWluY2V4KQpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGFudFssIDE1XSkpLCBtYWluPSJleHRpbmN0aW9uIG9mIEQgaW4gRiBlbnYiLCBjb2w9YWRqdXN0Y29sb3IoImNvcm5mbG93ZXJibHVlIiwgYWxwaGE9IDAuNyksIGJyZWFrcz0xMDAsIGJvcmRlcj1OQSwgeGxpbT0geGxpbWl0LCB5bGltPSB5bGltaXQsIGNleC5tYWluPSBtYWluY2V4LCBhZGQ9VFJVRSkKCmhpc3QoYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoZXh0aW5jdFssIDE2XSkpLCBtYWluPSJleHRpbmN0aW9uIG9mIEYgaW4gRCBlbnYiLCBjb2w9YWRqdXN0Y29sb3IoImZpcmVicmljayIsIGFscGhhPSAwLjcpLCBicmVha3M9MTAwLCBib3JkZXI9TkEsIHhsaW09IHhsaW1pdCwgeWxpbT0geWxpbWl0LCBjZXgubWFpbj0gbWFpbmNleCkKaGlzdChhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRhbnRbLCAxNl0pKSwgbWFpbj0iZXh0aW5jdGlvbiBvZiBGIGluIEQgZW52IiwgY29sPWFkanVzdGNvbG9yKCJjb3JuZmxvd2VyYmx1ZSIsIGFscGhhPSAwLjcpLCBicmVha3M9MTAwLCBib3JkZXI9TkEsIHhsaW09IHhsaW1pdCwgeWxpbT0geWxpbWl0LCBjZXgubWFpbj0gbWFpbmNleCwgYWRkPVRSVUUpCgpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGluY3RbLCAxN10pKSwgbWFpbj0iZXh0aW5jdGlvbiBvZiBEIGluIEQgZW52IiwgY29sPWFkanVzdGNvbG9yKCJmaXJlYnJpY2siLCBhbHBoYT0gMC43KSwgYnJlYWtzPTEwMCwgYm9yZGVyPU5BLCB4bGltPSB4bGltaXQsIHlsaW09IHlsaW1pdCwgY2V4Lm1haW49IG1haW5jZXgpCmhpc3QoYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoZXh0YW50WywgMTddKSksIG1haW49ImV4dGluY3Rpb24gb2YgRCBpbiBEIGVudiIsIGNvbD1hZGp1c3Rjb2xvcigiY29ybmZsb3dlcmJsdWUiLCBhbHBoYT0gMC43KSwgYnJlYWtzPTEwMCwgYm9yZGVyPU5BLCB4bGltPSB4bGltaXQsIHlsaW09IHlsaW1pdCwgY2V4Lm1haW49IG1haW5jZXgsIGFkZD1UUlVFKQoKIyMjIyMjCgpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGluY3RbLCAyOV0pKSwgbWFpbj0iYXJpc2FsIG9mIEYgaW4gRiBlbnYiLCBjb2w9YWRqdXN0Y29sb3IoImZpcmVicmljayIsIGFscGhhPSAwLjcpLCBicmVha3M9MTAwLCBib3JkZXI9TkEsIHhsaW09IHhsaW1pdCwgeWxpbT0geWxpbWl0LCBjZXgubWFpbj0gbWFpbmNleCkKaGlzdChhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRhbnRbLCAyOV0pKSwgbWFpbj0iYXJpc2FsIG9mIEYgaW4gRiBlbnYiLCBjb2w9YWRqdXN0Y29sb3IoImNvcm5mbG93ZXJibHVlIiwgYWxwaGE9IDAuNyksIGJyZWFrcz0xMDAsIGJvcmRlcj1OQSwgeGxpbT0geGxpbWl0LCB5bGltPSB5bGltaXQsIGNleC5tYWluPSBtYWluY2V4LCBhZGQ9VFJVRSkKCgoKaGlzdChhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRpbmN0WywgMzBdKSksIG1haW49ImFyaXNhbCBvZiBEIGluIEYgZW52IiwgY29sPWFkanVzdGNvbG9yKCJmaXJlYnJpY2siLCBhbHBoYT0gMC43KSwgYnJlYWtzPTEwMCwgYm9yZGVyPU5BLCB4bGltPSB4bGltaXQsIHlsaW09IHlsaW1pdCwgY2V4Lm1haW49IG1haW5jZXgpCmhpc3QoYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoZXh0YW50WywgMzBdKSksIG1haW49ImFyaXNhbCBvZiBEIGluIEYgZW52IiwgY29sPWFkanVzdGNvbG9yKCJjb3JuZmxvd2VyYmx1ZSIsIGFscGhhPSAwLjcpLCBicmVha3M9MTAwLCBib3JkZXI9TkEsIHhsaW09IHhsaW1pdCwgeWxpbT0geWxpbWl0LCBjZXgubWFpbj0gbWFpbmNleCwgYWRkPVRSVUUpCgpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGluY3RbLCAzMV0pKSwgbWFpbj0iYXJpc2FsIG9mIEYgaW4gRCBlbnYiLCBjb2w9YWRqdXN0Y29sb3IoImZpcmVicmljayIsIGFscGhhPSAwLjcpLCBicmVha3M9MTAwLCBib3JkZXI9TkEsIHhsaW09IHhsaW1pdCwgeWxpbT0geWxpbWl0LCBjZXgubWFpbj0gbWFpbmNleCkKaGlzdChhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRhbnRbLCAzMV0pKSwgbWFpbj0iYXJpc2FsIG9mIEYgaW4gRCBlbnYiLCBjb2w9YWRqdXN0Y29sb3IoImNvcm5mbG93ZXJibHVlIiwgYWxwaGE9IDAuNyksIGJyZWFrcz0xMDAsIGJvcmRlcj1OQSwgeGxpbT0geGxpbWl0LCB5bGltPSB5bGltaXQsIGNleC5tYWluPSBtYWluY2V4LCBhZGQ9VFJVRSkKCmhpc3QoYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoZXh0aW5jdFssIDMyXSkpLCBtYWluPSJhcmlzYWwgb2YgRCBpbiBEIGVudiIsIGNvbD1hZGp1c3Rjb2xvcigiZmlyZWJyaWNrIiwgYWxwaGE9IDAuNyksIGJyZWFrcz0xMDAsIGJvcmRlcj1OQSwgeGxpbT0geGxpbWl0LCB5bGltPSB5bGltaXQsIGNleC5tYWluPSBtYWluY2V4KQpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGFudFssIDMyXSkpLCBtYWluPSJhcmlzYWwgb2YgRCBpbiBEIGVudiIsIGNvbD1hZGp1c3Rjb2xvcigiY29ybmZsb3dlcmJsdWUiLCBhbHBoYT0gMC43KSwgYnJlYWtzPTEwMCwgYm9yZGVyPU5BLCB4bGltPSB4bGltaXQsIHlsaW09IHlsaW1pdCwgY2V4Lm1haW49IG1haW5jZXgsIGFkZD1UUlVFKQoKIyMjIyMjCgpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGluY3RbLCAxOV0pKSwgbWFpbj0iTk9QRSAtLSBEaWZmdXNpb246IHNvdXJjZSBGLCB0YXJnZXQgRiIsIGNvbD1hZGp1c3Rjb2xvcigiZmlyZWJyaWNrIiwgYWxwaGE9IDAuNyksIGJyZWFrcz0xMDAsIGJvcmRlcj1OQSwgeGxpbT0geGxpbWl0LCB5bGltPSBjKDAsMTgwMDApLCBjZXgubWFpbj0gbWFpbmNleCkKaGlzdChhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRhbnRbLCAxOV0pKSwgbWFpbj0iTk9QRSAtLSBEaWZmdXNpb246IHNvdXJjZSBGLCB0YXJnZXQgRiIsIGNvbD1hZGp1c3Rjb2xvcigiY29ybmZsb3dlcmJsdWUiLCBhbHBoYT0gMC43KSwgYnJlYWtzPTEwMCwgYm9yZGVyPU5BLCB4bGltPSB4bGltaXQsIHlsaW09IGMoMCwxODAwMCksIGNleC5tYWluPSBtYWluY2V4LCBhZGQ9VFJVRSkKCgoKaGlzdChhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRpbmN0WywgMjBdKSksIG1haW49IkRpZmZ1c2lvbjogc291cmNlIEQsIHRhcmdldCBGIiwgY29sPWFkanVzdGNvbG9yKCJmaXJlYnJpY2siLCBhbHBoYT0gMC43KSwgYnJlYWtzPTEwMCwgYm9yZGVyPU5BLCB4bGltPSB4bGltaXQsIHlsaW09IHlsaW1pdCwgY2V4Lm1haW49IG1haW5jZXgpCmhpc3QoYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoZXh0YW50WywgMjBdKSksIG1haW49IkRpZmZ1c2lvbjogc291cmNlIEQsIHRhcmdldCBGIiwgY29sPWFkanVzdGNvbG9yKCJjb3JuZmxvd2VyYmx1ZSIsIGFscGhhPSAwLjcpLCBicmVha3M9MTAwLCBib3JkZXI9TkEsIHhsaW09IHhsaW1pdCwgeWxpbT0geWxpbWl0LCBjZXgubWFpbj0gbWFpbmNleCwgYWRkPVRSVUUpCgpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGluY3RbLCAyMV0pKSwgbWFpbj0iRGlmZnVzaW9uOiBzb3VyY2UgRiwgdGFyZ2V0IEQiLCBjb2w9YWRqdXN0Y29sb3IoImZpcmVicmljayIsIGFscGhhPSAwLjcpLCBicmVha3M9MTAwLCBib3JkZXI9TkEsIHhsaW09IHhsaW1pdCwgeWxpbT0geWxpbWl0LCBjZXgubWFpbj0gbWFpbmNleCkKaGlzdChhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRhbnRbLCAyMV0pKSwgbWFpbj0iRGlmZnVzaW9uOiBzb3VyY2UgRiwgdGFyZ2V0IEQiLCBjb2w9YWRqdXN0Y29sb3IoImNvcm5mbG93ZXJibHVlIiwgYWxwaGE9IDAuNyksIGJyZWFrcz0xMDAsIGJvcmRlcj1OQSwgeGxpbT0geGxpbWl0LCB5bGltPSB5bGltaXQsIGNleC5tYWluPSBtYWluY2V4LCBhZGQ9VFJVRSkKCmhpc3QoYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoZXh0aW5jdFssIDIyXSkpLCBtYWluPSJOT1BFIC0tIERpZmZ1c2lvbjogc291cmNlIEQsIHRhcmdldCBEIiwgY29sPWFkanVzdGNvbG9yKCJmaXJlYnJpY2siLCBhbHBoYT0gMC43KSwgYnJlYWtzPTEwMCwgYm9yZGVyPU5BLCB4bGltPSB4bGltaXQsIHlsaW09IGMoMCwxODAwMCksIGNleC5tYWluPSBtYWluY2V4KQpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGFudFssIDIyXSkpLCBtYWluPSJOT1BFIC0tIERpZmZ1c2lvbjogc291cmNlIEQsIHRhcmdldCBEIiwgY29sPWFkanVzdGNvbG9yKCJjb3JuZmxvd2VyYmx1ZSIsIGFscGhhPSAwLjcpLCBicmVha3M9MTAwLCBib3JkZXI9TkEsIHhsaW09IHhsaW1pdCwgeWxpbT0gYygwLDE4MDAwKSwgY2V4Lm1haW49IG1haW5jZXgsIGFkZD1UUlVFKQoKIyMjIwoKaGlzdChhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRpbmN0WywgMjRdKSksIG1haW49IlRha2VvdmVyOiBzb3VyY2UgRiwgdGFyZ2V0IEYiLCBjb2w9YWRqdXN0Y29sb3IoImZpcmVicmljayIsIGFscGhhPSAwLjcpLCBicmVha3M9MTAwLCBib3JkZXI9TkEsIHhsaW09IHhsaW1pdCwgeWxpbT0geWxpbWl0LCBjZXgubWFpbj0gbWFpbmNleCkKaGlzdChhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRhbnRbLCAyNF0pKSwgbWFpbj0iVGFrZW92ZXI6IHNvdXJjZSBGLCB0YXJnZXQgRiIsIGNvbD1hZGp1c3Rjb2xvcigiY29ybmZsb3dlcmJsdWUiLCBhbHBoYT0gMC43KSwgYnJlYWtzPTEwMCwgYm9yZGVyPU5BLCB4bGltPSB4bGltaXQsIHlsaW09IHlsaW1pdCwgY2V4Lm1haW49IG1haW5jZXgsIGFkZD1UUlVFKQoKCgpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGluY3RbLCAyNV0pKSwgbWFpbj0iVGFrZW92ZXI6IHNvdXJjZSBELCB0YXJnZXQgRiIsIGNvbD1hZGp1c3Rjb2xvcigiZmlyZWJyaWNrIiwgYWxwaGE9IDAuNyksIGJyZWFrcz0xMDAsIGJvcmRlcj1OQSwgeGxpbT0geGxpbWl0LCB5bGltPSB5bGltaXQsIGNleC5tYWluPSBtYWluY2V4KQpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGFudFssIDI1XSkpLCBtYWluPSJUYWtlb3Zlcjogc291cmNlIEQsIHRhcmdldCBGIiwgY29sPWFkanVzdGNvbG9yKCJjb3JuZmxvd2VyYmx1ZSIsIGFscGhhPSAwLjcpLCBicmVha3M9MTAwLCBib3JkZXI9TkEsIHhsaW09IHhsaW1pdCwgeWxpbT0geWxpbWl0LCBjZXgubWFpbj0gbWFpbmNleCwgYWRkPVRSVUUpCgpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGluY3RbLCAyNl0pKSwgbWFpbj0iVGFrZW92ZXI6IHNvdXJjZSBGLCB0YXJnZXQgRCIsIGNvbD1hZGp1c3Rjb2xvcigiZmlyZWJyaWNrIiwgYWxwaGE9IDAuNyksIGJyZWFrcz0xMDAsIGJvcmRlcj1OQSwgeGxpbT0geGxpbWl0LCB5bGltPSB5bGltaXQsIGNleC5tYWluPSBtYWluY2V4KQpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGFudFssIDI2XSkpLCBtYWluPSJUYWtlb3Zlcjogc291cmNlIEYsIHRhcmdldCBEIiwgY29sPWFkanVzdGNvbG9yKCJjb3JuZmxvd2VyYmx1ZSIsIGFscGhhPSAwLjcpLCBicmVha3M9MTAwLCBib3JkZXI9TkEsIHhsaW09IHhsaW1pdCwgeWxpbT0geWxpbWl0LCBjZXgubWFpbj0gbWFpbmNleCwgYWRkPVRSVUUpCgpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGluY3RbLCAyN10pKSwgbWFpbj0iVGFrZW92ZXI6IHNvdXJjZSBELCB0YXJnZXQgRCIsIGNvbD1hZGp1c3Rjb2xvcigiZmlyZWJyaWNrIiwgYWxwaGE9IDAuNyksIGJyZWFrcz0xMDAsIGJvcmRlcj1OQSwgeGxpbT0geGxpbWl0LCB5bGltPSB5bGltaXQsIGNleC5tYWluPSBtYWluY2V4KQpoaXN0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGFudFssIDI3XSkpLCBtYWluPSJUYWtlb3Zlcjogc291cmNlIEQsIHRhcmdldCBEIiwgY29sPWFkanVzdGNvbG9yKCJjb3JuZmxvd2VyYmx1ZSIsIGFscGhhPSAwLjcpLCBicmVha3M9MTAwLCBib3JkZXI9TkEsIHhsaW09IHhsaW1pdCwgeWxpbT0geWxpbWl0LCBjZXgubWFpbj0gbWFpbmNleCwgYWRkPVRSVUUpCgoKZGV2Lm9mZigpCgoKCgoKCmBgYAoKCiFbXShHbG9iYWxfc3VjY2Vzc19yYXRlX3Blcl9wYXJhbWV0ZXIucG5nKQoKCmBgYHtyIGV2YWw9RkFMU0V9CgoKCnBuZyhmaWxlPSJleHRpY3Rpb24gbWludXMgZXh0YW50IHBlciBvdXRjb21lLnBuZyIsIHdpZHRoPTguNSwgaGVpZ2h0PTExLCB1bml0cz0iaW4iLCByZXM9MzAwKQpwYXIobWZyb3c9YygzLDEpKQoKcGxvdChhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRpbmN0Wyw5XSkpLCBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRpbmN0WywxNF0pKSwgeGxhYj0ic3BlY2lhdGlvbiIsIHlsYWI9ImV4dGluY3Rpb24iLCBjb2w9IGFkanVzdGNvbG9yKCJmaXJlYnJpY2siLCBhbHBoYT0wLjIpLCBwY2g9MTksIGNleD0wLjYsIHlsaW09YygwLDEpKQpwbG90KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGFudFssOV0pKSwgYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoZXh0YW50WywxNF0pKSwgeGxhYj0ic3BlY2lhdGlvbiIsIHlsYWI9ImV4dGluY3Rpb24iLCBjb2w9IGFkanVzdGNvbG9yKCJjb3JuZmxvd2VyYmx1ZSIsIGFscGhhPTAuMiksIHBjaD0xOSwgY2V4PTAuNiwgeWxpbT1jKDAsMSkpCgpwbG90KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGluY3RbLDldKSksIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGluY3RbLDE0XSkpLCB4bGFiPSJzcGVjaWF0aW9uIiwgeWxhYj0iZXh0aW5jdGlvbiIsIGNvbD0gYWRqdXN0Y29sb3IoImZpcmVicmljayIsIGFscGhhPTAuMiksIHBjaD0xOSwgY2V4PTAuNiwgeWxpbT1jKDAsMSkpCnBvaW50cyhhcy5udW1lcmljKGFzLmNoYXJhY3RlcihleHRhbnRbLDldKSksIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGV4dGFudFssMTRdKSksIHhsYWI9InNwZWNpYXRpb24iLCB5bGFiPSJleHRpbmN0aW9uIiwgY29sPSBhZGp1c3Rjb2xvcigiY29ybmZsb3dlcmJsdWUiLCBhbHBoYT0wLjIpLCBwY2g9MTksIGNleD0wLjYpCgoKZGV2Lm9mZigpCgoKYGBgCgohW10oZXh0aWN0aW9uIG1pbnVzIGV4dGFudCBwZXIgb3V0Y29tZS5wbmcpCgoKCmBgYHtyIGV2YWw9RkFMU0V9CgpwYXJhbXMgPC0gZXh0YW50WywtMTotMzVdCm5hbWVzKHBhcmFtcykKYnJlYWtfbnVtYmVyIDwtIDEwCnhtaW4gPC0KeG1heCA8LSAKCngxIDwtIGFzLm51bWVyaWMocGFyYW1zWywxXSkKaDEgPC0gaGlzdCh4MSwgIHBsb3Q9RkFMU0UsIGJyZWFrcz0gYnJlYWtfbnVtYmVyKQp4Zml0MSA8LSBzZXEoeG1pbiwgeG1heCwgbGVuZ3RoPSAxMDApCnlmaXQxIDwtIGRub3JtKHhmaXQxLCBtZWFuPW1lYW4oeDEpLCBzZD1zZCh4MSkpCnlmaXQxIDwtIHlmaXQxKmRpZmYoaDEkbWlkc1sxOjJdKSpsZW5ndGgoeDEpKzEwMS41CnBvbHlnb24oeGZpdDEsIHlmaXQxLCBjb2w9YWRqdXN0Y29sb3IoImxpbWVncmVlbiIsIGFscGhhPTAuNSksIGx3ZD0yLCBib3JkZXI9YWRqdXN0Y29sb3IoImxpbWVncmVlbiIsIGFscGhhPTAuNikpCgpgYGAKCgoKIyMgUnVuIGEgc2luZ2xlIHJhbmRvbSBmb3Jlc3Qgb24gYXZhaWxhYmxlIG91dHB1dHMKCmBgYHtyIGV2YWw9RkFMU0V9CgpzZXR3ZCgifi9Cb3ggU3luYy9jb2xsaWRpbmcgcmFuZ2VzL1NpbXVsYXRpb25zX2h1bWFucy9SZXN1bHRzL2F2YWlsYWJsZSBkYWlseSBzdW1tYXJpZXMiKQpkZXRhaWxzIDwtIGZpbGUuaW5mbyhsaXN0LmZpbGVzKCkpCgp0cmltbWVkX2RldGFpbHMgPC0gZGV0YWlsc1t3aGljaChsaXN0LmZpbGVzKCkgPT0gbGlzdC5maWxlcyhwYXR0ZXJuID0gIkZvdXJfbW9kZWxfY29tcGFyZV9yZXN1bHRzX2V4dGluY3QqIikpLF0Kb3JkIDwtIG9yZGVyKHRyaW1tZWRfZGV0YWlscyRtdGltZSwgZGVjcmVhc2luZyA9IFRSVUUpCnJvd25hbWVzKHRyaW1tZWRfZGV0YWlsc1tvcmQsXSlbMV0KbG9hZChyb3duYW1lcyh0cmltbWVkX2RldGFpbHNbb3JkLF0pWzFdKQpleHRpbmN0IDwtIENvbmNhdGVuYXRlZF9kYXRhCgp0cmltbWVkX2RldGFpbHMgPC0gZGV0YWlsc1t3aGljaChsaXN0LmZpbGVzKCkgIT0gbGlzdC5maWxlcyhwYXR0ZXJuID0gIkZvdXJfbW9kZWxfY29tcGFyZV9yZXN1bHRzX2V4dGluY3QqIikpLF0Kb3JkIDwtIG9yZGVyKHRyaW1tZWRfZGV0YWlscyRtdGltZSwgZGVjcmVhc2luZyA9IFRSVUUpCnJvd25hbWVzKHRyaW1tZWRfZGV0YWlsc1tvcmQsXSlbMV0KbG9hZChyb3duYW1lcyh0cmltbWVkX2RldGFpbHNbb3JkLF0pWzFdKQpleHRhbnQgPC0gQ29uY2F0ZW5hdGVkX2RhdGEKCgoKbG9hZCgnfi9Cb3ggU3luYy9jb2xsaWRpbmcgcmFuZ2VzL1NpbXVsYXRpb25zX2h1bWFucy9BdmFpbGFibGUgdHJlZXMvcmVhbC5hbmFseXNpcy5SRGF0YScpCgpDb25jYXRlbmF0ZWRfZGF0YSA8LSBleHRhbnQKaGVhZChDb25jYXRlbmF0ZWRfZGF0YSkKI0NvbmNhdGVuYXRlZF9kYXRhIDwtIENvbmNhdGVuYXRlZF9kYXRhW0NvbmNhdGVuYXRlZF9kYXRhWywgMl0gPT0gInN0YXRzLm5vLmJUTyIsIF0KI0NvbmNhdGVuYXRlZF9kYXRhIDwtIENvbmNhdGVuYXRlZF9kYXRhW0NvbmNhdGVuYXRlZF9kYXRhWywgNl0gIT0gIjA1IiwgXQojIENvbmNhdGVuYXRlZF9kYXRhWywgNl0gPC0gYXMubnVtZXJpYyhDb25jYXRlbmF0ZWRfZGF0YVssIDZdKQojICMgQ29uY2F0ZW5hdGVkX2RhdGFbb3JpZ2luYWxbLCAyXSA9PSAiYmFja2dyb3VuZF90YWtlb3ZlciIsIDZdIDwtICBDb25jYXRlbmF0ZWRfZGF0YVtvcmlnaW5hbFssIDJdID09ICJiYWNrZ3JvdW5kX3Rha2VvdmVyIiwgNl0gKyA0CkNvbmNhdGVuYXRlZF9kYXRhWywgNl0gPC0gZmFjdG9yKENvbmNhdGVuYXRlZF9kYXRhWywgNl0pCiNoZWFkKENvbmNhdGVuYXRlZF9kYXRhKQojbmFtZXMoQ29uY2F0ZW5hdGVkX2RhdGEpCgpQQ0FkYXRhIDwtIENvbmNhdGVuYXRlZF9kYXRhWywgLSgxOjM1KV0KUENBZGF0YSA8LSBQQ0FkYXRhWywgLTEyXQpQQ0FkYXRhIDwtIGFwcGx5KFBDQWRhdGEsIDIsIGFzLm51bWVyaWMpCnJlbW92ZSA8LSBhcHBseShpcy5uYShQQ0FkYXRhKSwgMSwgYW55KQpQQ0FkYXRhIDwtIFBDQWRhdGFbIXJlbW92ZSwgXQoKIyBQcmVkaWN0aW9ucwpsaWJyYXJ5KHJhbmRvbUZvcmVzdCkKCmRhdGEuYW5hbHlzaXMuY29tcDIgPC0gZGF0YS5mcmFtZSgiTW9kZWwiID0gYXMuZmFjdG9yKENvbmNhdGVuYXRlZF9kYXRhWyFyZW1vdmUsIDZdKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBDQWRhdGEpCmRhdGEuYW5hbHlzaXMuY29tcDIkc3ByYXRlIDwtIGRhdGEuYW5hbHlzaXMuY29tcDIkdHJhaXRfMV9zcGVjaWF0aW9uL2RhdGEuYW5hbHlzaXMuY29tcDIkdHJhaXRfMl9zcGVjaWF0aW9uCmRhdGEuYW5hbHlzaXMuY29tcDIkZXh0cmF0ZSA8LSBkYXRhLmFuYWx5c2lzLmNvbXAyJHRyYWl0XzFfZXh0aW5jdGlvbi9kYXRhLmFuYWx5c2lzLmNvbXAyJHRyYWl0XzJfZXh0aW5jdGlvbgoKCiNsb2FkKCJSZWFsX3BoeS9yZWFsLmFuYWx5c2lzLlJEYXRhIikKYSA8LSBhcy5kYXRhLmZyYW1lKHJlYWwuYW5hbHlzaXMkcmVzdWx0c19zdW1tYXJ5X29mX3NpbmdsZV92YWx1ZV9vdXRwdXRzKQphJHNwcmF0ZSA8LSBhJHRyYWl0XzFfc3BlY2lhdGlvbiAvIGEkdHJhaXRfMl9zcGVjaWF0aW9uCmEkZXh0cmF0ZSA8LSBhJHRyYWl0XzFfZXh0aW5jdGlvbiAvIGEkdHJhaXRfMl9leHRpbmN0aW9uCgpkYXRhLmFuYWx5c2lzLmNvbXAzIDwtIGRhdGEuYW5hbHlzaXMuY29tcDJbLCAtYygyLCAxMzoxNCwgMTY6MjApXQojZGF0YS5hbmFseXNpcy5jb21wMyA8LSBkYXRhLmFuYWx5c2lzLmNvbXAzW2RhdGEuYW5hbHlzaXMuY29tcDMkTW9kZWwgJWluJSAxOjQsIF0KI2RhdGEuYW5hbHlzaXMuY29tcDMkTW9kZWwgPC0gZmFjdG9yKGRhdGEuYW5hbHlzaXMuY29tcDMkTW9kZWwpCiNzdWIgPC0gdW5saXN0KGxhcHBseShhcy5saXN0KGMoMTo0KSksIGZ1bmN0aW9uKHgsIHkpIHsKIyAgc2FtcGxlKHdoaWNoKHkkTW9kZWwgPT0geCksIG1pbih0YWJsZShkYXRhLmFuYWx5c2lzLmNvbXAzJE1vZGVsKSkpfSwKIyAgeSA9IGRhdGEuYW5hbHlzaXMuY29tcDMpKQojIGRhdGEuYW5hbHlzaXMuY29tcDMgPC0gZGF0YS5hbmFseXNpcy5jb21wM1tzdWIsIF0KZnVuIDwtIGZ1bmN0aW9uKHgsIHksIHBlciA9IC4zMykge3NhbXBsZSh3aGljaCh5JE1vZGVsID09IHgpLCByb3VuZCh0YWJsZSh5JE1vZGVsKVsxXSpwZXIpKX0KCnN1Yi50ZXN0IDwtIHVubGlzdChsYXBwbHkoYXMubGlzdChwYXN0ZTAoMCwgYygxOjQpKSksIGZ1biwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gZGF0YS5hbmFseXNpcy5jb21wMykpCnRlc3QyIDwtIGRhdGEuYW5hbHlzaXMuY29tcDNbc3ViLnRlc3QsIDI6bmNvbChkYXRhLmFuYWx5c2lzLmNvbXAzKV0KdGVzdDEgPC0gZGF0YS5hbmFseXNpcy5jb21wM1tzdWIudGVzdCwgMV0KdHJhaW4gPC0gZGF0YS5hbmFseXNpcy5jb21wM1stc3ViLnRlc3QsIF0KCnRyYWluWywgLTFdIDwtIGFwcGx5KHRyYWluWywgLTFdLCAyLCBhcy5udW1lcmljKQp0ZXN0MiA8LSBhcy5kYXRhLmZyYW1lKGFwcGx5KHRlc3QyLCAyLCBhcy5udW1lcmljKSkKaW5maW5pdGVzIDwtIHdoaWNoKGFwcGx5KHRyYWluWywgLTFdLCAyLCBpcy5pbmZpbml0ZSksIGFyci5pbmQ9VCkKaWYgKG5yb3coaW5maW5pdGVzKSA+IDApIHsKdHJhaW4gPC0gdHJhaW5bLWluZmluaXRlc1ssIDFdLCBdCn0KaW5maW5pdGVzMiA8LSB3aGljaChhcHBseSh0ZXN0MiwgMiwgaXMuaW5maW5pdGUpLCBhcnIuaW5kPVQpCmlmIChucm93KGluZmluaXRlczIpID4gMCkgewp0ZXN0MiA8LSB0ZXN0MlstaW5maW5pdGVzMlssIDFdLCBdCnRlc3QxIDwtIHRlc3QxWy1pbmZpbml0ZXMyWywgMV1dCn0KCgpmb3IoaSBpbiAxOjEwMCl7CihmaXQgPC0gcmFuZG9tRm9yZXN0KE1vZGVsIH4gLiwgZGF0YT10cmFpbiwgeHRlc3QgPSB0ZXN0MiwgeXRlc3QgPSB0ZXN0MSwgCiAgICAgICAgICAgICAgICAgICAgaW1wb3J0YW5jZT1UUlVFLCBudHJlZT0xMDAwLCBrZWVwLmZvcmVzdCA9IFRSVUUsIHJlcGxhY2U9RkFMU0UpKQoKcHJlZGljdGlvbnMgPC0gcHJlZGljdChmaXQsIAogICAgICAgICAgICAgICAgICAgICAgIGEsCiAgICAgICAgICAgICAgICAgICAgICAgdHlwZT0icHJvYiIpCnByZWRpY3Rpb25zCgpzYXZlKGZpdCwgZmlsZT1wYXN0ZTAoIn4vQm94IFN5bmMvY29sbGlkaW5nIHJhbmdlcy9TaW11bGF0aW9uc19odW1hbnMvUmVzdWx0cy9SRl9kYWlseV9vdXRwdXQvUkZfZGFpbHlfb3V0cHV0XyIsIGZvcm1hdChTeXMudGltZSgpLCBmb3JtYXQ9IiVkXyViXyVZIiksICJfIixpLCAiX05vUkVQTEFDRU1FTlRfLlJkYXRhIikpCn0KYGBgCgpgYGB7ciBldmFsPUZBTFNFfQoKCnNhdmUoZml0LCBmaWxlPXBhc3RlMCgifi9Cb3ggU3luYy9jb2xsaWRpbmcgcmFuZ2VzL1NpbXVsYXRpb25zX2h1bWFucy9SZXN1bHRzL1JGX2RhaWx5X291dHB1dC9SRl9kYWlseV9vdXRwdXRfIiwgZm9ybWF0KFN5cy50aW1lKCksIGZvcm1hdD0iJWRfJWJfJVkiKSwiLlJkYXRhIikpCmBgYAoKCiMjIFZpc3VhbGl6ZSBvdXRwdXRzIGZyb20gUmFuZG9tIEZvcmVzdCBhbmFseXNpcwoKYGBge3IgZXZhbD1GQUxTRX0KCnBsb3QoZml0LCB5bGltPWMoMCwxKSkKCmBgYAoKCgoKYGBge3IgZXZhbD1GQUxTRX0KbGFicyA8LSBjKCJCYXNpYyIsICIrRGlmZnVzaW9uIiwgIitUYWtlb3ZlciIsICIrRGlmZnVzaW9uICtUYWtlb3ZlciIpCgpgYGAKCgpgYGB7ciBldmFsPUZBTFNFfQojIGJhciBwbG90CnBuZygiUHJvYl9hdXMucG5nIiwgd2lkdGggPSAyNSwgaGVpZ2h0ID0gMjUsIHJlcyA9IDMwMCwgdW5pdHMgPSAiaW4iKQpwYXIobWFyID0gYyg4LCA4LCAxLCAxKSkKcHJlZCA8LSBzZXROYW1lcyhhcy5udW1lcmljKHByZWRpY3Rpb25zKSwgbGFicykKY29scyA8LSByZXYoYygiZGFya2dyZWVuIiwgInJlZCIsICJibHVlIiwgImRhcmtvcmFuZ2UxIikpCmJhcnBsb3QocHJlZCwgY29sID0gY29scywgeWxhYiA9ICJQcm9hYmlsaXR5IiwgY2V4LmxhYiA9IDMsIGNleC5uYW1lcyA9IDIpCmRldi5vZmYoKQpgYGAKCiFbXShQcm9iX2F1cy5wbmcpCgoKYGBge3IgZXZhbD1GQUxTRX0KIyBQbG90IGNvbmZ1c2lvbiBtYXRyaXgKcG5nKCJDb25mZnVzaW9uX21hdHJpeF9hbGwucG5nIiwgd2lkdGggPSAyNSwgaGVpZ2h0ID0gMjUsIHJlcz0zMDAsIHVuaXRzPSJpbiIpCnBhcihtYXIgPSBjKDEwLCAxMSwgMSwgMSkpCmNvbG9yczEgPC0gY29sb3JSYW1wUGFsZXR0ZShjb2xvcnMgPSBjKCIjZjBmMGYwIiwgIiNiZGJkYmQiLCIjNjM2MzYzIikpCnByb3AgPC0gYXBwbHkoZml0JGNvbmZ1c2lvblssIC01XSwgMiwgZnVuY3Rpb24oeCl7eCAvIHN1bSh4KX0pICogMTAwCgppbWFnZShwcm9wLCBjb2wgPSBjb2xvcnMxKDIwKSwgYXhlcz1GQUxTRSkKYXhpcygxLCBhdD1jKDAsIC4zMywgLjY2LCAxKSwgbGFiZWxzPWxhYnMsIHRpY2sgPSBGQUxTRSwgbGluZSA9IEZBTFNFLCBjZXguYXhpcyA9IDMuNSwgcG9zID0gLS4xOSkKYXhpcygyLCBhdD1jKDAsIC4zMywgLjY2LCAxKSwgbGFiZWxzPWxhYnMsIHRpY2sgPSBGQUxTRSwgbGluZSA9IEZBTFNFLCBjZXguYXhpcyA9IDMuNSkKbXRleHQoIkFDVFVBTCIsIHNpZGUgPSAxLCBwYWRqID0gMywgY2V4ID0gNCkKbXRleHQoIlBSRURJQ1RFRCIsIHNpZGUgPSAyLCBwYWRqID0gLTMsIGNleCA9IDQpCgpmb3IoaSBpbiAxOjQpIHsKICBmb3IoaiBpbiAxOjQpIHsKICAgIHRleHQoeCA9IGMoMCwgLjMzLCAuNjYsIDEpW2ldLCB5ID0gYygwLCAuMzMsIC42NiwgMSlbal0sIHBhc3RlMChyb3VuZChwcm9wW2ksIGpdLCAyKSwgIiUiKSwKICAgICAgICAgY2V4ID0gNSkKICB9Cn0KZGV2Lm9mZigpCmBgYAoKCiFbXShDb25mZnVzaW9uX21hdHJpeF9hbGwucG5nKQoKCmBgYHtyIGV2YWw9RkFMU0V9CmltcG9ydGFuY2UoZml0KQpgYGAKCgpgYGB7ciBldmFsPUZBTFNFfQojIFZhcmlhYmxlcyBpbXBvcnRhbmNlCgppbXAgPC0gaW1wb3J0YW5jZShmaXQpCmltcCA8LSBhcHBseShpbXAsIDIsIGZ1bmN0aW9uKHgpICh4IC0gbWluKHgpKS8obWF4KHgpIC0gbWluKHgpKSkKaW1wIDwtIGltcFtzb3J0KGltcFssIDVdLCBpbmRleC5yZXR1cm4gPSBUUlVFLCBkZWNyZWFzaW5nID0gVFJVRSkkaXgsIF0KCgpuYW1lcyA8LSByb3duYW1lcyhpbXApCm5hbWVzW25hbWVzID09ICJzcGF0aWFsLnRlc3RzLmZvcmEiXSA8LSAiU3BhY2UgRiIKbmFtZXNbbmFtZXMgPT0gInNwYXRpYWwudGVzdHMuZG9tIl0gPC0gIlNwYWNlIEQiCm5hbWVzW25hbWVzID09ICJzcHJhdGUiXSA8LSAiU3AocmF0aW8pIgpuYW1lc1tuYW1lcyA9PSAidHJhbnNpdGlvbl9mcm9tX3RyYWl0XzFfdG9fMiJdIDwtICJUUigxLTIpIgpuYW1lc1tuYW1lcyA9PSAidHJhbnNpdGlvbl9mcm9tX3RyYWl0XzJfdG9fMSJdIDwtICJUUigyLTEpIgpuYW1lc1tuYW1lcyA9PSAiUGh5bG9nZW5ldGljX3NpZ25hbCJdIDwtICJQaHlTaWcoRCkiCm5hbWVzW25hbWVzID09ICJFdm9sdXRpb25hcnlfZGlzdGluY3RpdmVuZXNzX3N1bSJdIDwtICJFRHN1bSIKbmFtZXNbbmFtZXMgPT0gIlB5bG9fZGl2ZXJzaXR5X2lzX3N1bV9vZl9CTCJdIDwtICJQRHN1bSIKbmFtZXNbbmFtZXMgPT0gInRyYW5zaXRpb25fcmF0ZV9yYXRpb18xdG8yX292ZXJfMnRvMSJdIDwtICJUUihyYXRpbykiCm5hbWVzW25hbWVzID09ICJnYW1tYSJdIDwtICJHYW1tYSIKbmFtZXNbbmFtZXMgPT0gIm1lYW5fUGh5bG9nZW5ldGljX2lzb2xhdGlvbiJdIDwtICJNUEkiCm5hbWVzW25hbWVzID09ICJleHRyYXRlIl0gPC0gIkV4dChyYXRpbykiCm5hbWVzW25hbWVzID09ICJhdmVyYWdlX3BoeWxvZ2VuZXRpY19kaXZlcnNpdHlfaXNfbWVhbl9vZl9CTCJdIDwtICJQRG1lYW4iCm5hbWVzW25hbWVzID09ICJleHRpbmN0aW9uX3Blcl9zcGVjaWF0aW9uIl0gPC0gIkRSIgpuYW1lc1tuYW1lcyA9PSAidmFyaWFuY2VfUGh5bG9nZW5ldGljX2lzb2xhdGlvbiJdIDwtICJWUEkiCm5hbWVzW25hbWVzID09ICJGX3F1YWRyYXRpY19lbnRyb3B5X2lzX3N1bV9vZl9QRCJdIDwtICJGIgpuYW1lc1tuYW1lcyA9PSAiTWVhbl9wYWlyd2lzZV9kaXN0YW5jZSJdIDwtICJNUEQiCm5hbWVzW25hbWVzID09ICJ2YXJpYW5jZV9QeWxvX2RpdmVyc2l0eV9pc192YXJpYW5jZV9vZl9CTCJdIDwtICJQRHZhciIKbmFtZXNbbmFtZXMgPT0gInZhcmlhbmNlX3BhaXJ3aXNlX2Rpc3RhbmNlIl0gPC0gIlZQRCIKCgpwbmcoInZhcl9pbXBvcnRfYWxsLnBuZyIsIHdpZHRoID0gMjUsIGhlaWdodCA9IDI1LCB1bml0PSJpbiIsIHJlcz0zMDApCnBhcihtYXIgPSBjKDEwLCAxOCwgMSwgMSkpCnBsb3QoeCA9IHJldihpbXBbLCA1XSksIHkgPSAxOm5yb3coaW1wKSwgdHlwZSA9ICJsIiwgeWF4dCA9ICJuIiwgCiAgICAgeWxhYiA9ICIiLCB4bGFiID0gIlZhcmlhYmxlIEltcG9ydGFuY2UiLAogICAgIHhsaW0gPSBjKDAsIDEpLCBsd2QgPSAyLCBjZXgubGFiID0gNCkKZm9yIChpIGluIDE6bnJvdyhpbXApKSB7CiAgYWJsaW5lKGggPSBpLCBsdHkgPSAzLCBjb2wgPSAiZ3JheTgwIikKfQphYmxpbmUodiA9IHNlcSgwLCAxLCAxLzE5KSwgbHR5ID0gMywgY29sID0gImdyYXk4MCIpCgpsaW5lcyh4ID0gcmV2KGltcFssIDRdKSwgeSA9IDE6bnJvdyhpbXApLCBjb2wgPSAiZGFya2dyZWVuIiwgbHdkID0gMikKbGluZXMoeCA9IHJldihpbXBbLCAzXSksIHkgPSAxOm5yb3coaW1wKSwgY29sID0gInJlZCIsIGx3ZCA9IDIpCmxpbmVzKHggPSByZXYoaW1wWywgMl0pLCB5ID0gMTpucm93KGltcCksIGNvbCA9ICJibHVlIiwgbHdkID0gMikKbGluZXMoeCA9IHJldihpbXBbLCAxXSksIHkgPSAxOm5yb3coaW1wKSwgY29sID0gImRhcmtvcmFuZ2UxIiwgbHdkID0gMikKbGluZXMoeCA9IHJldihpbXBbLCA1XSksIHkgPSAxOm5yb3coaW1wKSwgbHdkID0gMykKCnBvaW50cyh4ID0gcmV2KGltcFssIDRdKSwgeSA9IDE6bnJvdyhpbXApLCBjb2wgPSAiZGFya2dyZWVuIiwgY2V4ID0gMikKcG9pbnRzKHggPSByZXYoaW1wWywgM10pLCB5ID0gMTpucm93KGltcCksIGNvbCA9ICJyZWQiLCBjZXggPSAyKQpwb2ludHMoeCA9IHJldihpbXBbLCAyXSksIHkgPSAxOm5yb3coaW1wKSwgY29sID0gImJsdWUiLCBjZXggPSAyKQpwb2ludHMoeCA9IHJldihpbXBbLCAxXSksIHkgPSAxOm5yb3coaW1wKSwgY29sID0gImRhcmtvcmFuZ2UxIiwgY2V4ID0gMikKcG9pbnRzKHggPSByZXYoaW1wWywgNV0pLCB5ID0gMTpucm93KGltcCksIHBjaCA9IDIwLCBjZXggPSAzKQoKCnRleHQoeSA9IDE6bnJvdyhpbXApLCB4ID0gcGFyKCJ1c3IiKVsxXSAtIC4xNywgbGFiZWxzID0gcmV2KG5hbWVzKSwKICAgICBzcnQgPSAwLCBwb3MgPSA0LCB4cGQgPSBULCBjZXggPSA0KQpkZXYub2ZmKCkKYGBgCgohW10odmFyX2ltcG9ydF9hbGwucG5nKQoKCgoKYGBge3IgZXZhbD1GQUxTRX0KcGFyKG1mcm93PWMoMiwzKSkKCiMgQm94IHBsb3RzCmJveHBsb3Qoc3BhdGlhbC50ZXN0cy5mb3JhIH4gTW9kZWwsIGRhdGEgPSBkYXRhLmFuYWx5c2lzLmNvbXAzKQphYmxpbmUoaCA9IGEkc3BhdGlhbC50ZXN0cy5mb3JhLCBjb2wgPSAicmVkIiwgbHR5ID0gMikKCmJveHBsb3Qoc3BhdGlhbC50ZXN0cy5kb20gfiBNb2RlbCwgZGF0YSA9IGRhdGEuYW5hbHlzaXMuY29tcDMpCmFibGluZShoID0gYSRzcGF0aWFsLnRlc3RzLmZvcmEsIGNvbCA9ICJyZWQiLCBsdHkgPSAyKQoKYm94cGxvdChsb2coc3ByYXRlKSB+IE1vZGVsLCBkYXRhID0gZGF0YS5hbmFseXNpcy5jb21wMywgeWxpbSA9IGMoLTEwLCAxMCkpCmFibGluZShoID0gbG9nKGEkc3ByYXRlKSwgY29sID0gInJlZCIsIGx0eSA9IDIpCgpib3hwbG90KGxvZyhleHRyYXRlKSB+IE1vZGVsLCBkYXRhID0gZGF0YS5hbmFseXNpcy5jb21wMywgeWxpbSA9IGMoLTEwLCAxMCkpCmFibGluZShoID0gbG9nKGEkZXh0cmF0ZSksIGNvbCA9ICJyZWQiLCBsdHkgPSAyKQoKYm94cGxvdChsb2codHJhbnNpdGlvbl9yYXRlX3JhdGlvXzF0bzJfb3Zlcl8ydG8xKSB+IE1vZGVsLCBkYXRhID0gZGF0YS5hbmFseXNpcy5jb21wMykKYWJsaW5lKGggPSBsb2coYSRzcHJhdGUpLCBjb2wgPSAicmVkIiwgbHR5ID0gMikKCmJveHBsb3QoUGh5bG9nZW5ldGljX3NpZ25hbCB+IE1vZGVsLCBkYXRhID0gZGF0YS5hbmFseXNpcy5jb21wMywgeWxpbSA9IGMoMCwgMSkpCmFibGluZShoID0gYSRQaHlsb2dlbmV0aWNfc2lnbmFsLCBjb2wgPSAicmVkIiwgbHR5ID0gMikKCgpgYGAKCgoKYGBge3IgZXZhbD1GQUxTRX0KI2J1aWxkIGEgZGF0YSB0cmFja2luZyB0YWJsZSB0byB0cmFjayBwYXJhbWV0ZXIgY2hhbmdlcyB0aHJvdWdoIHRpbWUKCnN0cihmaXQpCgp5CgpgYGAKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg==